Add RunInChildContextAsync#2370
Conversation
d943d16 to
7ca2099
Compare
e146869 to
369a029
Compare
7ca2099 to
5a29b3e
Compare
369a029 to
5a29b3e
Compare
There was a problem hiding this comment.
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 forSUCCEEDED,FAILED,STARTED/PENDING. - Public surface additions:
IDurableContext.RunInChildContextAsync(typed and void overloads),ChildContextConfig,ChildContextException. - Service-client mapping extended to copy
ContextDetails(Result, partialError) 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.
8e29ff3 to
097e5a1
Compare
8058cdf to
4132f5d
Compare
|
|
||
| COPY bin/publish/ ${LAMBDA_TASK_ROOT} | ||
|
|
||
| ENTRYPOINT ["/var/task/bootstrap"] |
|
|
||
| COPY bin/publish/ ${LAMBDA_TASK_ROOT} | ||
|
|
||
| ENTRYPOINT ["/var/task/bootstrap"] |
59ed6b8 to
9f45bf3
Compare
|
|
||
| COPY bin/publish/ ${LAMBDA_TASK_ROOT} | ||
|
|
||
| ENTRYPOINT ["/var/task/bootstrap"] |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
Libraries/src/Amazon.Lambda.DurableExecution/Internal/StepOperation.cs:283
- On first-time step failure (non-replay), the thrown StepException only sets ErrorType. Since the FAIL checkpoint includes stack trace (and may include ErrorData), replay will surface OriginalStackTrace/ErrorData but fresh execution will not, which is inconsistent with the StepException contract (“original error details”). Consider populating these properties from the same error payload you checkpoint so callers see consistent metadata across fresh vs replay failures.
await EnqueueAsync(new SdkOperationUpdate
{
Id = OperationId,
ParentId = ParentId,
Type = OperationTypes.Step,
Action = OperationAction.FAIL,
SubType = OperationSubTypes.Step,
Name = Name,
Error = ToSdkError(ex)
}, cancellationToken);
throw new StepException(ex.Message, ex)
{
ErrorType = ex.GetType().FullName
};
9f45bf3 to
1f53406
Compare
| { | ||
| ErrorType = sdkOp.StepDetails.Error.ErrorType, | ||
| ErrorMessage = sdkOp.StepDetails.Error.ErrorMessage | ||
| ErrorMessage = sdkOp.StepDetails.Error.ErrorMessage, |
There was a problem hiding this comment.
not related to child context, but missed copying the error details before here
| /// Configuration for a child context. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// A child context is a logical sub-workflow with its own deterministic |
There was a problem hiding this comment.
ctx.StepAsync(..., "validate"); // root #1
ctx.RunInChildContextAsync(child => { // root #2 (the CONTEXT op)
child.StepAsync(..., "charge"); // child #1
child.StepAsync(..., "ship"); // child #2
}, name: "phase");
ctx.StepAsync(..., "notify"); // root #3Resulting IDs:
| Op | Id | ParentId |
|---|---|---|
| validate | h("1") | null |
| phase | h("2") | null |
| charge | h("h("2")-1") | h("2") |
| ship | h("h("2")-2") | h("2") |
| notify | h("3") | null |
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>
c4ea83e to
607f219
Compare
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#2216
What
Adds child-context support to
Amazon.Lambda.DurableExecutionon top of #2360. A user function can now run inside a logical sub-workflow with its own deterministic operation-ID space; the result is checkpointed as aCONTEXToperation so subsequent invocations replay the cached value without re-executing the func.Public API:
IDurableContext.RunInChildContextAsync<T>(...)T.IDurableContext.RunInChildContextAsync(...)ChildContextConfigSubType(observability label) +ErrorMapping(exception remapping).ChildContextExceptionSubType,ErrorType,ErrorData,OriginalStackTrace.How
Internal/ChildContextOperation<T>mirrors the Step/Wait pattern from #2360:CONTEXT STARTcheckpoint, then invokes the user func with a childIDurableContext. The child has its own operation-ID counter, so steps/waits inside it get deterministic IDs scoped to the child. On success the SDK writesSUCCEEDwith the serialized result; on throw it writesFAILwith the error details and throwsChildContextException.SUCCEEDEDreturns the cached value (deserialized via the registeredILambdaSerializer).FAILEDreconstructs and throwsChildContextException(afterErrorMapping, if provided).STARTED/PENDINGre-runs the func and lets the child's own operations replay from their own checkpoints — a child whose inner step suspended will re-suspend the same way.ILambdaContext.Serializer(consistent withStepOperation);FAILEDcheckpoint, so callers see the same exception type either way.LambdaDurableServiceClient.MapFromSdkOperationis extended to copyContextDetails(Result+Error) for the newCONTEXToperation kind.This is a building block for upcoming
WaitForCallbackAsync, which (per the Java/JS reference SDKs) wrapsCreateCallbackAsync+ a submitter step inside a child context for observability and clean error mapping.Testing
14 new unit tests in
ChildContextOperationTests.cs:CONTEXT START-> user func ->SUCCEED).SUCCEEDEDreturns cached value without re-running.FAILEDthrowsChildContextException, with and withoutErrorMapping.Waitinside child propagates termination correctly.STARTEDwith completed inner step.SubTypepropagation to the wire.161/161 tests pass on net8.0 and net10.0. Production build clean: 0 warnings, 0 errors.
Out of scope (follow-up PRs)
WaitForCallbackAsync/CreateCallbackAsync/InvokeAsyncMapAsync/ParallelAsync/WaitForConditionAsyncDefaultJsonCheckpointSerializerDurableLoggerreplay-suppression (currentlyNullLogger)[DurableExecution]attributeDurableTestRunner/Amazon.Lambda.DurableExecution.Testingpackagedotnet new lambda.DurableFunctionblueprint