Skip to content

feat(sdk): preserve child-context operations across resume for observability#714

Merged
ParidelPooya merged 1 commit into
mainfrom
feat/preserve-child-operations
Jul 14, 2026
Merged

feat(sdk): preserve child-context operations across resume for observability#714
ParidelPooya merged 1 commit into
mainfrom
feat/preserve-child-operations

Conversation

@ParidelPooya

Copy link
Copy Markdown
Contributor

Adds an opt-in way to keep child-context operations (parallel branches, map items, and their nested operations) visible to instrumentation plugins after a suspend/resume, plus a plugin knob to choose how much of the tree to report.

Core (@aws/durable-execution-sdk-js):

  • New DurableExecutionConfig.pluginsConfig.childOperationsDepth. By default the backend prunes a finished context's children from the state handed to later invocations, so a snapshot taken after a wait only sees top-level operations. This numeric depth preserves them: 1 = children of top-level contexts (map items, parallel branches), 2 = their children, Infinity = whole tree, omitted = off (unchanged behavior).
  • Implemented via a per-context depth budget carried on DurableContext: the root is seeded with depth+1, each nested context decrements by one (Infinity stays Infinity, floored at 0), and executeChildContext forces ReplayChildren when a context's budget >= 1. Since parallel/map route through runInChildContext, one change covers branches, map items, and nested steps.
  • ReplayChildren keeps the children in execution state and rebuilds the parent result by REPLAYING the already-checkpointed children on resume — the children are not re-executed (no step bodies/side effects run again). Cost is the extra replay pass, documented on the config field. Default behavior is unchanged (budget never reaches >= 1 without opt-in).

Plugin (@aws/durable-execution-sdk-js-insight):

  • New WorkflowInsightConfig.operationDetail: "full-tree" (default) or "top-level" (drops any operation with a parentId) for a consistent, resume-independent snapshot. Pair "full-tree" with childOperationsDepth to keep the full tree across resume.

@ParidelPooya
ParidelPooya force-pushed the feat/preserve-child-operations branch 9 times, most recently from e44dc0d to 7c8595d Compare July 13, 2026 22:47
…ability

Adds an opt-in way to keep child-context operations (parallel branches, map
items, and their nested operations) visible to instrumentation plugins after a
suspend/resume, and a plugin knob to choose how much of the tree to report.

Core (@aws/durable-execution-sdk-js):
- New `DurableExecutionConfig.pluginsConfig.childOperationsDepth`. By default the
  backend prunes a finished context's children from the state handed to later
  invocations, so a snapshot taken after a wait only sees top-level operations.
  This numeric depth preserves them: 1 = children of top-level contexts (map
  items, parallel branches), 2 = their children, Infinity = whole tree, omitted
  = off (unchanged behavior).
- Config is validated up front through a single validateDurableExecutionConfig
  entry point (extensible as the config surface grows). An invalid value is a
  non-retryable configuration error that fails the execution immediately —
  before the handler runs — by returning FAILED (not throwing, so Lambda does
  not retry). childOperationsDepth must be a non-negative integer or Infinity.
  Validation/mapping helpers live in internal modules (not re-exported from the
  package entrypoint), so they stay unit-testable without leaking to the public API.
- Implemented via a per-context depth budget carried on DurableContext: the root
  is seeded with depth+1, each nested context decrements by one (Infinity stays
  Infinity, floored at 0), and executeChildContext forces ReplayChildren when a
  context's budget >= 1. Since parallel/map route through runInChildContext, one
  change covers branches, map items, and nested steps.
- Depth counts the VISIBLE operation tree: virtual wrapper contexts (map/parallel
  FLAT nesting) don't checkpoint and re-parent their children onto the ancestor,
  so the budget is passed through unchanged for them (no off-by-one for contexts
  nested inside a FLAT item). The runInChildContext overload disambiguation is a
  single shared resolveChildArgs helper used by both the handler and the context.
- Applies to both SUCCEEDED and FAILED contexts: the FAIL checkpoint also sets
  ReplayChildren within the depth, so the children of a failed branch survive
  resume (important for emitMode "on-failure"). A failed context throws its
  checkpointed error on replay and is never re-executed, so this adds no cost.
- ReplayChildren keeps the children in execution state and rebuilds a succeeded
  context's result by REPLAYING the already-checkpointed children on resume —
  the children are not re-executed (no step bodies/side effects run again). Cost
  is the extra replay pass, documented on the config field. Default behavior is
  unchanged (budget never reaches >= 1 without opt-in).
- Tests: SUCCEED and FAIL checkpoints carry ContextOptions.ReplayChildren at
  budgets 1/2/Infinity and not at 0/undefined/negative (full payload preserved);
  per-level decrement, Infinity, default, virtual-context passthrough;
  resolveChildArgs, the depth validate/resolve helpers, and
  validateDurableExecutionConfig; and two examples integration tests
  (child-operations-preservation drives a real suspend/resume and asserts a
  FAILED context still carries its children so the cloud integ run catches
  backend differences; child-operations-invalid-depth asserts an invalid depth
  fails the execution).

Plugin (@aws/durable-execution-sdk-js-insight):
- New `WorkflowInsightConfig.operationDetail`: "top-level" (default) or
  "full-tree". Default is top-level so snapshots are consistent regardless of
  suspend/resume; "full-tree" is opt-in and pairs with childOperationsDepth for
  a complete tree across resume. Documented both (and the replay cost) in the
  insight README.

Verified: core tsc + full suite (1057 tests), insight tsc + tests (48), and both
examples tests locally.
@ParidelPooya
ParidelPooya force-pushed the feat/preserve-child-operations branch from 7c8595d to edae4a9 Compare July 13, 2026 22:54
@ParidelPooya
ParidelPooya marked this pull request as ready for review July 14, 2026 01:34
@ParidelPooya
ParidelPooya merged commit 36f954f into main Jul 14, 2026
16 checks passed
@ParidelPooya
ParidelPooya deleted the feat/preserve-child-operations branch July 14, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants