Skip to content

Add virtual-context support to standalone RunInChildContextAsync#2463

Merged
GarrettBeatty merged 1 commit into
devfrom
issue-2461
Jul 8, 2026
Merged

Add virtual-context support to standalone RunInChildContextAsync#2463
GarrettBeatty merged 1 commit into
devfrom
issue-2461

Conversation

@GarrettBeatty

Copy link
Copy Markdown
Contributor

Issue

Closes #2461

The .NET Durable Execution SDK exposed virtual (flat) contexts only through the concurrent MapAsync/ParallelAsync paths (NestingType.Flat). There was no equivalent option for a standalone RunInChildContextAsync, so users porting Java/JS examples that manually fan out child contexts and await them with Task.WhenAll had to switch to MapAsync/ParallelAsync.

Investigation

The SDK internals already fully supported virtual standalone child contexts:

  • ChildContextOperation<T> takes an isVirtual flag and suppresses its own CONTEXT START/SUCCEED/FAIL checkpoints while still propagating results and exceptions.
  • DurableContext.MakeChildFactory handles the virtual case via OperationIdGenerator.CreateVirtualChild, re-parenting inner operations to the nearest non-virtual ancestor.

The only missing piece was public API surface + wiring for the standalone entry point.

Referencing the JS SDK as ground truth, ChildConfig.virtualContext?: boolean drives isVirtual = options?.virtualContext === true in the run-in-child-context handler, which skips checkpoints and re-parents inner ops when virtual.

Change

I chose the NestingType shape (the issue's first suggestion) rather than a virtualContext/IsVirtual bool, because it matches the existing convention on MapConfig and ParallelConfig — consistent for .NET consumers, identical wire behavior to the JS virtualContext bool.

  • ChildContextConfig.NestingType — new property, defaults to NestingType.Nested.
  • DurableContext.RunChildContext — passes isVirtual: config?.NestingType == NestingType.Flat to the operation.

Users can now write the exact shape requested in the issue:

await context.RunInChildContextAsync(
    async (childContext, ct) =>
        await childContext.StepAsync(
            (_, stepCt) => Task.FromResult("result"),
            name: "compute",
            cancellationToken: ct),
    name: "child-0",
    config: new ChildContextConfig { NestingType = NestingType.Flat });

Tests

Added 3 tests to ChildContextOperationTests:

  • RunInChildContextAsync_FlatNesting_EmitsNoContextCheckpointAndReparentsInnerOps — Flat emits no CONTEXT checkpoint; inner ops re-parent to the non-virtual ancestor.
  • RunInChildContextAsync_FlatNesting_ReplayReExecutesBodyFromInnerCheckpoint — with no CONTEXT checkpoint, replay re-executes the body while inner steps replay from their own checkpoints (mirrors JS "virtual: re-execute then round-trip").
  • RunInChildContextAsync_FlatNesting_FuncThrows_EmitsNoFailCheckpointButPropagates — Flat suppresses the CONTEXT FAIL checkpoint but still propagates the exception.

Build: clean (0 warnings). Tests: 408/408 pass on net8.0 and net10.0.

Change file

Included: .autover/changes/durable-childcontext-virtual.json (Minor, Amazon.Lambda.DurableExecution).

The SDK internals already supported virtual child contexts (ChildContextOperation
takes isVirtual; MakeChildFactory re-parents inner ops via CreateVirtualChild),
but the only public entry point was the concurrent Map/Parallel path via
NestingType.Flat. Standalone RunInChildContextAsync had no way to opt in.

Add ChildContextConfig.NestingType (default Nested), matching the existing
convention on MapConfig/ParallelConfig, and wire RunChildContext to pass
isVirtual when NestingType.Flat is set. Under Flat the child emits no CONTEXT
checkpoint of its own; inner operations re-parent to the nearest non-virtual
ancestor and replay from their own checkpoints, mirroring the JS SDK's
virtualContext behavior.

Closes #2461
@GarrettBeatty GarrettBeatty marked this pull request as ready for review July 7, 2026 22:07
@GarrettBeatty GarrettBeatty requested review from a team as code owners July 7, 2026 22:07
@GarrettBeatty GarrettBeatty requested review from normj and philasmar July 7, 2026 22:07
@GarrettBeatty GarrettBeatty merged commit 34314b1 into dev Jul 8, 2026
5 checks passed
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.

3 participants