aws / aws/aws-durable-execution-sdk-js

Plugin info gaps: end-info isFirstInvocation, failed-attempt timestamps, isReplayingChildren

Open
#803 0 comments 0 reactions 1 assignee Claimed by @wangyb-A View on GitHub
Dominant language
TypeScript
Stars
84
Forks
28
Avg merge
1d 19h
Merged PRs (30d)
43

Description

## Summary
Three invocation/attempt info gaps versus the other SDKs:
1. `isFirstInvocation` exists only on the start-hook `InvocationInfo`; `InvocationEndInfo` does not carry it. Python and Java both expose it on their end infos — a 2-vs-1 divergence against JS.
2. `AttemptEndInfo` omits `endTimestamp` (and can omit `startTimestamp`) on FAILED retryable attempt-ends — the info is backfilled from the checkpointed operation (`toAttemptEndInfo(stepData, ...)` + `backfillOperationInfo`, `src/handlers/step-handler/step-handler.ts` ~457-465), and a retry-pending operation has no end timestamp yet. Python and Java stamp attempt-scoped times (`now()` at attempt end) and pass. The attempt DID end; its end info should say when.
3. `wrapChildContextFn` — JS's plugin hook for context-type user functions (parallel branch / map item / child-context bodies) — cannot express whether the body's children are replaying. Its info is `{...opInfo, isReplay: childReplayMode !== ExecutionMode}` (`src/handlers/run-in-child-context-handler/run-in-child-context-handler.ts:376-385`), where `opInfo` is identity only (`id`, `name`, `type`, `subType`, `parentId` — line 329, no `status`). Because `determineChildReplayMode` (same file, line 44) returns `ReplaySucceededContext` when `stepData.ContextDetails?.ReplayChildren` is set but `ReplayMode` for a plain SUCCEEDED/FAILED context, `isReplay: true` covers BOTH cases and nothing else in the payload disambiguates them — so a plugin cannot derive children-replay by any means. Python (`is_replay_children`) and Java (`isReplayingChildren`) expose the flag directly, from the same checkpointed `ContextDetails.ReplayChildren` source.

## Missing fields (verified against `src/types/plugin.ts` + `step-handler.ts`)
- **`InvocationEndInfo.isFirstInvocation`**
- **`AttemptEndInfo.endTimestamp`/`startTimestamp` population on FAILED attempts** (type declares them; the failed-attempt path doesn't populate)
- **`isReplayingChildren` on `wrapChildContextFn`'s info** (field absent from the JS SDK entirely; `isReplay` there is a conflated two-mode boolean)

## Evidence
Conformance requirements 10-19/10-21/10-23 (aws/aws-durable-execution-conformance-tests#72), canonical-dump handlers in #800 — live run 20/23:
- 10-19 red only on the two invocation-end `isFirstInvocation` assertions.
- 10-21 red only on the attempt-1 FAILED end matcher's timestamp assertions; the SUCCEEDED attempt-2 end matcher (same timestamps) passes.
- 10-23 red: no children-replay indicator for the named parallel branches (branch-a/branch-b), so all four name-correlated `isReplayingChildren` probes fail. Python and Java pass, including custom branch-name propagation onto their context user-function infos. (The suite's JS handler currently probes `onOperationAttemptStart`, which never fires for context bodies; switching it to `wrapChildContextFn` would emit records carrying `name`/`subType`/`parentId` and localize the red to the single missing field.)

All asserted gaps are metadata — unaffected by the GA payload descope. (Note: execution input/result payload surfaces were moved out of GA conformance scope and are no longer asserted; JS exposes them and they remain visible in the dumps, unjudged.)

## Impact
(1) Plugins classifying invocation-end records must capture the first flag at start and carry it across hooks (conformance 10-16's handler needs exactly this workaround). (2) Duration metrics for failed attempts cannot be computed from the attempt-end info. (3) Plugins observing context-function re-runs cannot distinguish "this body is re-running so its children replay" from "this context's result is being replayed" — the two have different observability meaning (e.g. OTel span suppression) and are indistinguishable today.

## Suggested fix
(1) Add `isFirstInvocation: boolean` to `InvocationBaseInfo` (or `InvocationEndInfo`). (2) Stamp attempt-scoped start/end times on `AttemptEndInfo` in the failed-attempt path instead of relying on operation-level backfill. (3) Add `isReplayingChildren` to the `wrapChildContextFn` info at the existing construction site — `childReplayMode` is already in scope, so it is a one-line, additive, design-preserving change (no new hooks, no change to `wrapChildContextFn`'s wrap-style contract):

```typescript
const wrapInfo = {
...opInfo,
isReplay: childReplayMode !== DurableExecutionMode.ExecutionMode,
isReplayingChildren: childReplayMode === DurableExecutionMode.ReplaySucceededContext,
};
```

Items 1+2 flip 10-19/10-21 green; item 3 flips 10-23 green (once the suite's JS handler probes `wrapChildContextFn`). No changes to the requirements are needed.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.