Skip to content

[Testing]: Prune completed-context descendants from replay state #858

Open

Description

@zhongkechen

Split from PR #795 — match replay state to the service, reference commit f8ac9b4; baseline main is d7ae95571c44b18c2a2efdef9a308b1c916c5049. This issue owns one independently implementable slice of that PR. Start a focused branch from current main and port only this slice, rather than stacking on the full PR.

Problem and reproduction

The local runner builds invocation input and state-read pages from the complete retained operation list. A completed CONTEXT without ReplayChildren: true therefore exposes descendants that should be absent from the replay view. This can hide replay-visibility bugs in SDKs and plugins.

Create a stored tree containing a SUCCEEDED or FAILED context with a child step, plus a second completed context with ReplayChildren: true. Read invocation input and GetDurableExecutionState, including small paginated reads. The first context's descendants should be absent; the explicitly retained descendants should remain. Raw inspection/history must still contain both trees.

Scope and implementation

  • Apply the same retained-operation rule at invocation/state-read boundaries before pagination. Keep checkpoint deltas, raw stores, history, and result inspection complete.
  • Walk known ancestors, including through STARTED intermediate contexts. A descendant's own retention flag cannot override an ancestor that prunes it. Preserve input order and retain roots/orphans whose parent is unavailable.
  • Use the retained operation count for marker validation. Preserve stale/malformed/out-of-range marker checks without a second unused raw-snapshot validation mode.
  • Reuse the existing paginator and keep stored operations unchanged. Any cycle handling must have an explicit supported-input rationale and focused test.

Primary code: prune_replay_children in operation_state.py, OperationPaginatorState.page / _resolve_marker in execution.py, and CheckpointProcessor.get_execution_state in processor.py.

Acceptance criteria

  • Cover succeeded/failed ancestors, explicit retention, running intermediates, nested retained contexts beneath a pruning ancestor, reversed input ordering, and missing parents.
  • Every visible operation is returned exactly once across item/byte-bounded pages; markers are validated against the visible list.
  • Both in-process and Lambda invocation inputs and state reads agree across memory/filesystem stores.
  • Checkpoint deltas, raw operation inspection, and history retain hidden descendants. An updated ID alone does not manufacture missing metadata.
  • Public-handler resume returns saved outcomes without repeating completed step bodies.
  • Adjust test_builtin_operation_categories_survive_suspend_and_replay so live hooks still cover every category while replay asserts the retained categories. Document this expected change.
  • Add the replay visibility explanation to the testing README/architecture documentation.

Reference tests and review constraints

Also see the core plugin_operation_type_int_test.py. Four retained-state cases failed against the baseline testing source during #795 validation and passed with the full PR; establish the same result for this smaller slice.

Address the unnecessary marker fallback. Do not copy the optional SERVICE_PRUNING_PROOF_DIR exporter from the reference test: review found it untested and outside the required assertions.

Independence

Seed existing ContextDetails with explicit flags to test filtering independently of the separate ReplayChildren serialization fix. This issue owns which records appear, not flag encoding, callback update production/acknowledgment, error normalization, or OTel export behavior. The reference operation_state.py is new; adding just the filtering function does not require its serialization helper. #854 remains the separate OTel consumer fix.

Validation and evidence

Add a regression that fails on main without this fix and passes with this slice alone. Run from the repository root:

hatch run dev-testing:test
hatch run dev-testing:typecheck
hatch run dev-testing:js-examples

Use the repository's CI-pinned Hatch version (1.16.5 at the reference) and Node.js 22+ for the JS harness; run hatch fmt --check from packages/aws-durable-execution-sdk-python-testing. Use public-handler integration tests for cross-component behavior and both memory/filesystem stores where relevant. List changed test expectations and their reasons in the implementing PR.

The service-parity expectations are carried forward from #795. This split does not independently verify them against deployed AWS Lambda; cite service evidence or mark the external assumption unverified before claiming deployed-service qualification. Shared conformance work belongs to #796 / conformance PR #131; coordinate new requirements there.

Related issues in this split

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions