Menu

Synchronous Mode and Testing

Relevant source files

This page documents synchronous mode, a special execution mode that evaluates mirai tasks immediately in the current process, and the test suite architecture used to verify package functionality.

For information about asynchronous evaluation (the default mode), see Asynchronous Evaluation with mirai(). For error handling and observability in production environments, see Error Handling and Control.


Overview

Synchronous mode (sync = TRUE) fundamentally changes how mirai tasks are evaluated by running them immediately in the current R process rather than sending them to background daemons. This mode serves two primary purposes:

  1. Testing and Debugging: Enables interactive debugging with browser() and step-through execution
  2. Test Suite Execution: Provides deterministic, traceable execution for automated tests

When synchronous mode is active, all daemon-related arguments to daemons() are ignored, and tasks execute as if they were regular R function calls.

Sources: vignettes/mirai.Rmd720-754 R/daemons.R44-48 R/daemons.R251-255


Enabling Synchronous Mode

Basic Activation

Call daemons() with sync = TRUE to enable synchronous mode for the default compute profile:

This configuration:

  • Sets url to local_url() internally
  • Forces dispatcher = FALSE
  • Ignores remote, serial, tls, and pass arguments
  • Only respects seed and .compute parameters

Sources: R/daemons.R251-255 vignettes/mirai.Rmd731-733

Profile-Specific Synchronous Mode

Restrict synchronous behavior to a named compute profile:

This allows mixing synchronous and asynchronous profiles within the same session. Tasks sent to the "debug" profile execute synchronously, while other profiles operate normally.

Sources: vignettes/mirai.Rmd724-725 vignettes/mirai.Rmd743-754

Synchronous Mode Implementation Flow

Diagram: Synchronous Mode Initialization in daemons()

Sources: R/daemons.R251-255 R/daemons.R647-653 R/daemons.R655-666


Synchronous Execution Behavior

Execution Path Differences

Diagram: Async vs Sync Execution Paths

Sources: vignettes/mirai.Rmd722-723

Code Entity Mapping

In synchronous mode, the following code paths are altered:

Normal PathSync PathLocation
mirai() creates unresolved objectmirai() evaluates immediatelyR/mirai.R22-90
Evaluation in daemon processEvaluation in host processR/daemons.R251-255
Result fetched via socketResult available immediatelyR/daemons.R308
dispatcher queues tasksNo dispatcher or queueR/daemons.R252

Sources: R/daemons.R251-255 vignettes/mirai.Rmd720-725


Use Cases for Synchronous Mode

Interactive Debugging

Synchronous mode enables interactive debugging sessions using browser():

In async mode, browser() would execute in a background daemon process where interactive input is not available.

Sources: vignettes/mirai.Rmd722-723

Deterministic Testing

The test suite uses implicit synchronous execution when no daemons are set. This provides:

  • Reproducibility: Same input always produces same output
  • Traceability: Stack traces show actual code locations
  • Isolation: No concurrent execution or race conditions
  • Simplicity: No need to manage daemon lifecycle in tests

Sources: tests/tests.R17-156

Profile-Scoped Debugging

Isolate debugging to specific task types:

Sources: vignettes/mirai.Rmd742-754 man/with_daemons.Rd31-60


Test Suite Architecture

Minitest Framework

The package uses a custom minimal testing framework defined in tests/tests.R1-14:

Diagram: Minitest Framework Structure

Sources: tests/tests.R1-14

Test Function Definitions

FunctionPurposeImplementation
test_library()Load packagetests/tests.R2
test_true()Assert TRUEtests/tests.R3
test_false()Assert FALSEtests/tests.R4
test_null()Assert NULLtests/tests.R5
test_notnull()Assert not NULLtests/tests.R6
test_zero()Assert 0Ltests/tests.R7
test_type()Assert typeof()tests/tests.R8
test_class()Assert classtests/tests.R9
test_equal()Assert ==tests/tests.R10
test_identical()Assert identicaltests/tests.R11
test_print()Assert printabletests/tests.R12
test_error()Assert error with messagetests/tests.R13

Each test function invisibly returns TRUE on success or stops execution with an informative error message on failure.

Sources: tests/tests.R1-14


Test Organization

Test Suite Structure

Diagram: Test Suite Organization

Sources: tests/tests.R1-521

Test Categories

1. Setup and Core Validation (lines 16-75)

Tests basic functionality without daemons:

  • info() returns NULL when no daemons set
  • status() returns list with zero connections
  • daemons(0) returns FALSE when no daemons exist
  • Error handling for invalid arguments
  • URL construction functions

Sources: tests/tests.R16-75

2. Mirai and Daemons Integration (lines 76-156)

Tests mirai evaluation with daemons:

  • Basic mirai creation and evaluation
  • .args and .expr parameters
  • call_mirai() and race_mirai()
  • Error handling with miraiError
  • Stack traces and condition classes
  • everywhere() functionality
  • Compute profiles

Sources: tests/tests.R76-156

3. Synchronous Mode Tests (lines 298-309)

Validates synchronous mode behavior:

Key validation points:

  • daemons(sync = TRUE) succeeds
  • everywhere() works in sync mode
  • Tasks execute immediately
  • launch_local() and launch_remote() error appropriately
  • Tasks can be created but not collected until profile is reset
  • Result values are correct (including missing() test)

Sources: tests/tests.R298-309


Test Patterns

Conditional Test Execution

Tests check for network connectivity before running distributed tests:

Sources: tests/tests.R17 tests/tests.R77-156

Environment Variable Guards

Certain tests only run in development environments:

This prevents complex tests (TLS, OpenTelemetry, stress tests) from running on CRAN's test infrastructure where they may be unreliable.

Sources: tests/tests.R265 tests/tests.R312 tests/tests.R338

Timing and Synchronization

Tests use explicit sleep calls to ensure daemons connect:

This pattern appears throughout the test suite to avoid race conditions in asynchronous operations.

Sources: tests/tests.R78 tests/tests.R88 tests/tests.R98

Error Message Validation

Tests verify specific error messages using test_error():

The containing parameter ensures the error message includes expected text.

Sources: tests/tests.R24-38


Integration with Synchronous Mode

Test Suite Execution Model

Diagram: Test Suite Execution Flow

Sources: tests/tests.R17-521

Synchronous Mode in Test Context

When synchronous mode is tested:

  1. Profile Creation: tests/tests.R298 creates "seq" compute profile
  2. Scoped Execution: tests/tests.R299 uses with_daemons() for scoping
  3. State Persistence: tests/tests.R300-305 validates everywhere() and immediate execution
  4. Launch Prevention: tests/tests.R302-303 ensures launchers error correctly
  5. Deferred Evaluation: tests/tests.R304-308 tests that results remain valid after profile reset

Sources: tests/tests.R298-309


Best Practices

When to Use Synchronous Mode

Use synchronous mode for:

  • Interactive debugging with browser()
  • Step-through debugging of complex expressions
  • Reproducing race conditions deterministically
  • Testing without daemon overhead
  • Validating expression logic in isolation

Do not use synchronous mode for:

  • Production workloads
  • Performance benchmarking
  • Testing parallel execution behavior
  • Distributed computing scenarios

Sources: vignettes/mirai.Rmd720-725

Combining Sync and Async Profiles

Example pattern for mixed-mode debugging:

This pattern allows investigating specific failures while maintaining normal execution for the bulk of work.

Sources: vignettes/mirai.Rmd742-754 man/with_daemons.Rd32-60

Test Development Workflow

  1. Write test using synchronous mode for rapid iteration
  2. Validate with test_* functions
  3. Add to test suite with appropriate guards
  4. Verify in async mode with real daemons
  5. Add NOT_CRAN guard if test requires complex setup

Sources: tests/tests.R1-521


Summary

Synchronous mode transforms mirai from an asynchronous parallel computing framework into a synchronous, single-process execution model. This dual-mode capability enables:

  • Development: Interactive debugging and immediate feedback
  • Testing: Deterministic, reproducible test execution
  • Validation: Verifying expression logic without daemon complexity

The test suite demonstrates best practices for using synchronous mode alongside the minitest framework to ensure comprehensive package validation.

Sources: vignettes/mirai.Rmd720-754 R/daemons.R44-48 R/daemons.R251-255 tests/tests.R1-521