Skip to content

Latest commit

 

History

History
79 lines (56 loc) · 2.25 KB

File metadata and controls

79 lines (56 loc) · 2.25 KB

Deterministic local runner

The local runner executes durable handlers in process using local_service_client, a protocol-level implementation of service_client. Production workflow code is unchanged.

Virtual time

The runner never sleeps. When an invocation returns PENDING, it advances to the earliest automatic event:

  • WAIT completion;
  • STEP retry becoming READY;
  • a mocked chained-invoke result;
  • execution timeout;
  • optionally, callback timeout or heartbeat timeout.

All events due at the selected virtual timestamp are applied before the next invocation. local_test_result::virtual_time() exposes the resulting clock.

Callbacks stop execution with pending_external by default, allowing tests to inspect the generated callback ID and respond:

auto pending = runner.run();
auto id = pending.pending_callback_ids().front();
runner.send_callback_success(id, serialized_result);
auto complete = runner.resume();

Use advance_time() to test callback deadlines manually, or set auto_advance_callback_timeouts=true.

Chained invoke mocks

Register serialized results before running:

runner.mock_invoke_success("worker:prod", R"({"status":"ok"})");

Unmocked chained invokes produce pending_external. Failure mocks accept an error_object.

Result statuses

local_run_status distinguishes:

  • succeeded;
  • failed;
  • pending_external;
  • deadlocked — the handler returned pending without a resumable operation;
  • invocation_limit_exceeded;
  • timed_out.

The invocation limit protects tests from nondurable retry loops.

History inspection

Each local_test_result owns immutable copies of:

  • final invocation output;
  • operation history;
  • checkpoint updates;
  • invocation count;
  • virtual time.

Convenience lookups include operation_by_id, operation_by_name, step, wait, pending_callback_ids, and typed deserialize_result.

Fidelity boundaries

The runner validates checkpoint tokens, operation identity, and lifecycle transitions. It supports batching and parallel calls because its service implementation is mutex-protected.

It intentionally omits AWS networking, IAM, service throttling, retention, and distributed callback delivery. Those behaviors belong to deployed integration and conformance tests.