Skip to content

Add RunInChildContextAsync#2370

Draft
GarrettBeatty wants to merge 1 commit into
GarrettBeatty/stack/3from
gcbeatty/durable-child-context
Draft

Add RunInChildContextAsync#2370
GarrettBeatty wants to merge 1 commit into
GarrettBeatty/stack/3from
gcbeatty/durable-child-context

Conversation

@GarrettBeatty
Copy link
Copy Markdown
Contributor

@GarrettBeatty GarrettBeatty commented May 14, 2026

Summary

  • Adds RunInChildContextAsync to IDurableContext with two overloads: returning T and void.
  • Adds ChildContextConfig (SubType for observability, ErrorMapping for exception remapping) and ChildContextException for failure surfacing.
  • Implements Internal/ChildContextOperation<T> mirroring the Step/Wait pattern: sync-flush CONTEXT START -> run user func -> emit SUCCEED with serialized result, or FAIL with error and throw ChildContextException. Replay: SUCCEEDED returns cached value, FAILED throws (after ErrorMapping), STARTED/PENDING re-runs the func and lets the child's own operations replay from their own checkpoints.
  • Result serialization uses the ILambdaSerializer registered on ILambdaContext.Serializer (consistent with StepOperation); no separate AOT overload is needed since the AOT story is owned by the registered serializer (e.g. SourceGeneratorLambdaJsonSerializer<TContext>).
  • Extends LambdaDurableServiceClient.MapFromSdkOperation to copy ContextDetails (Result + Error).

This is a building block for upcoming WaitForCallbackAsync, which (per the Java/JS reference SDKs) wraps CreateCallbackAsync + a submitter step inside a child context for observability and clean error mapping.

#2216

Test plan

  • 14 new tests in ChildContextOperationTests.cs covering: fresh execution + checkpoint emission, deterministic child operation IDs, replay SUCCEEDED, replay FAILED (with and without ErrorMapping), suspended child (Wait inside child propagates termination), replay STARTED with completed inner step, void overload, type-mismatch non-determinism detection, and SubType propagation.
  • 161/161 tests pass on net8.0 and net10.0 (existing Step/Wait tests untouched).
  • Production build clean: 0 warnings, 0 errors.

@GarrettBeatty GarrettBeatty force-pushed the GarrettBeatty/stack/3 branch from d943d16 to 7ca2099 Compare May 14, 2026 18:07
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-child-context branch 2 times, most recently from e146869 to 369a029 Compare May 14, 2026 21:49
@GarrettBeatty GarrettBeatty force-pushed the GarrettBeatty/stack/3 branch from 7ca2099 to 5a29b3e Compare May 17, 2026 20:16
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-child-context branch from 369a029 to 5a29b3e Compare May 17, 2026 20:27
Adds child-context support to the .NET Durable Execution SDK. A child
context is a logical sub-workflow with its own deterministic
operation-ID space, persisted as a CONTEXT operation so subsequent
invocations replay the cached value without re-executing the function.

Public surface:
- IDurableContext.RunInChildContextAsync<T> (reflection + AOT-safe
  ICheckpointSerializer<T> overloads, plus a void overload).
- ChildContextConfig with SubType (observability label) and
  ErrorMapping (transform exceptions before they surface to the caller).
- ChildContextException for failure surfacing.

Used as a building block for upcoming WaitForCallbackAsync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a RunInChildContextAsync API to IDurableContext enabling user functions to be executed inside a logical sub-workflow whose result is checkpointed as a CONTEXT operation. The child context shares the parent's state, termination manager, batcher, and Lambda context, but uses a child OperationIdGenerator so its operation IDs are deterministically namespaced. Failures are surfaced via a new ChildContextException, optionally remapped via ChildContextConfig.ErrorMapping. This is positioned as a building block for a future WaitForCallbackAsync.

Changes:

  • New ChildContextOperation<T> mirroring the Step/Wait pattern with replay branches for SUCCEEDED, FAILED, STARTED/PENDING.
  • Public surface additions: IDurableContext.RunInChildContextAsync (typed and void overloads), ChildContextConfig, ChildContextException.
  • Service-client mapping extended to copy ContextDetails (Result, partial Error) from SDK responses, plus 14 new unit tests.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Libraries/src/Amazon.Lambda.DurableExecution/IDurableContext.cs Adds typed/void RunInChildContextAsync to the public interface.
Libraries/src/Amazon.Lambda.DurableExecution/DurableContext.cs Implements RunInChildContextAsync and constructs ChildContextOperation with a child-context factory.
Libraries/src/Amazon.Lambda.DurableExecution/Internal/ChildContextOperation.cs New operation type implementing fresh execution, replay, and failure paths.
Libraries/src/Amazon.Lambda.DurableExecution/ChildContextConfig.cs New config type with SubType and ErrorMapping.
Libraries/src/Amazon.Lambda.DurableExecution/DurableExecutionException.cs Adds ChildContextException with SubType, ErrorType, ErrorData, OriginalStackTrace.
Libraries/src/Amazon.Lambda.DurableExecution/Services/LambdaDurableServiceClient.cs Maps ContextDetails from the SDK operation; drops ErrorData/StackTrace.
Libraries/test/Amazon.Lambda.DurableExecution.Tests/ChildContextOperationTests.cs 14 tests covering fresh, replay, suspension, error-mapping, and non-determinism paths.
Libraries/test/Amazon.Lambda.DurableExecution.Tests/LambdaDurableServiceClientTests.cs New test for ContextDetails Result/Error copy.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +132 to 140
ContextDetails = sdkOp.ContextDetails != null ? new Internal.ContextDetails
{
Result = sdkOp.ContextDetails.Result,
Error = sdkOp.ContextDetails.Error != null ? new ErrorObject
{
ErrorType = sdkOp.ContextDetails.Error.ErrorType,
ErrorMessage = sdkOp.ContextDetails.Error.ErrorMessage
} : null
} : null
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