Skip to content

Add InvokeAsync for chained durable function calls (DOTNET-8661)#2374

Open
GarrettBeatty wants to merge 4 commits into
feature/durablefunctionfrom
gcbeatty/durable-invoke
Open

Add InvokeAsync for chained durable function calls (DOTNET-8661)#2374
GarrettBeatty wants to merge 4 commits into
feature/durablefunctionfrom
gcbeatty/durable-invoke

Conversation

@GarrettBeatty
Copy link
Copy Markdown
Contributor

@GarrettBeatty GarrettBeatty commented May 14, 2026

#2216

What

Adds chained-function invocation to Amazon.Lambda.DurableExecution. InvokeAsync calls another durable function as a separate execution; the caller suspends until the chained function completes, with the result checkpointed for replay. Mirrors the Python/JS/Java reference SDKs.

Public API:

Type Purpose
IDurableContext.InvokeAsync<TPayload, TResult>(...) Invoke another durable Lambda function and await its result. Single overload — payload and result are serialized via the ILambdaSerializer registered on ILambdaContext.Serializer, so AOT and reflection callers share one code path (the AOT story is decided by the registered serializer, e.g. SourceGeneratorLambdaJsonSerializer<TContext>).
InvokeConfig Optional config: TenantId (propagated to the chained invocation) and Timeout ([Obsolete] placeholder reserved for a future ChainedInvokeOptions wire field).
InvokeException Base exception for chained-invoke failures; carries FunctionName, ErrorType, ErrorData, OriginalStackTrace.
InvokeFailedException Subclass — chained function ran and threw.
InvokeTimedOutException Subclass — chained function did not complete within the configured / service timeout.
InvokeStoppedException Subclass — chained execution was stopped by the service before reaching a normal terminal state.


COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]

COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]

COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]

COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]

COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]

COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]

COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]

COPY bin/publish/ ${LAMBDA_TASK_ROOT}

ENTRYPOINT ["/var/task/bootstrap"]
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-invoke branch from 2e91110 to a7868f3 Compare May 14, 2026 21:49
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-wave0 branch from 464c591 to d308c3b Compare May 14, 2026 21:49
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-invoke branch from a7868f3 to 797d920 Compare May 14, 2026 22:19
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-wave0 branch from d308c3b to be4c3ad Compare May 18, 2026 15:23
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-invoke branch from 797d920 to a659aa8 Compare May 18, 2026 15:42
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-wave0 branch 3 times, most recently from ad4d208 to 3acbed5 Compare May 20, 2026 17:46
Base automatically changed from gcbeatty/durable-wave0 to gcbeatty/durable-child-context May 20, 2026 17:46
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-child-context branch 2 times, most recently from 4d97473 to 8a6c41c Compare May 21, 2026 18:56
Base automatically changed from gcbeatty/durable-child-context to feature/durablefunction May 23, 2026 15:58
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-invoke branch 3 times, most recently from 65a2a50 to f3d103d Compare May 29, 2026 15:32
@GarrettBeatty GarrettBeatty requested a review from Copilot May 29, 2026 15:33
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 durable chained invocation support so a workflow can checkpoint a CHAINED_INVOKE, suspend, and resume with a cached child result or typed failure.

Changes:

  • Adds IDurableContext.InvokeAsync<TPayload, TResult>, InvokeConfig, invoke operation replay/suspend logic, and invoke-specific exception types.
  • Extends SDK operation mapping and replay terminal-state tracking for chained invoke details and timeouts.
  • Adds unit and integration coverage for happy path, failure propagation, replay determinism, and tenant propagation.

Reviewed changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Libraries/src/Amazon.Lambda.DurableExecution/DurableContext.cs Implements InvokeAsync entry point and validation.
Libraries/src/Amazon.Lambda.DurableExecution/IDurableContext.cs Adds public chained invoke API documentation/signature.
Libraries/src/Amazon.Lambda.DurableExecution/Internal/InvokeOperation.cs Adds checkpoint, suspend, replay, serialization, and exception mapping for chained invokes.
Libraries/src/Amazon.Lambda.DurableExecution/InvokeConfig.cs Adds invoke configuration type.
Libraries/src/Amazon.Lambda.DurableExecution/InvokeException.cs Adds invoke exception hierarchy.
Libraries/src/Amazon.Lambda.DurableExecution/Internal/ExecutionState.cs Treats timed-out operations as terminal for replay tracking.
Libraries/src/Amazon.Lambda.DurableExecution/Services/LambdaDurableServiceClient.cs Maps chained invoke details and centralizes SDK error mapping.
Docs/durable-execution-design.md Updates design documentation for invoke exceptions.
Libraries/test/Amazon.Lambda.DurableExecution.Tests/InvokeOperationTests.cs Adds unit coverage for invoke operation behavior.
Libraries/test/Amazon.Lambda.DurableExecution.Tests/LambdaDurableServiceClientTests.cs Adds error-field round-trip coverage.
Libraries/test/Amazon.Lambda.DurableExecution.Tests/ExecutionStateTests.cs Covers timed-out replay terminal tracking.
Libraries/test/Amazon.Lambda.DurableExecution.Tests/ExceptionsTests.cs Covers invoke exception hierarchy.
Libraries/test/Amazon.Lambda.DurableExecution.Tests/ConfigTests.cs Covers invoke config defaults/properties.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/DurableFunctionDeployment.cs Extends integration deployment helper for parent/downstream functions.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/InvokeHappyPathTest.cs Adds chained invoke happy-path integration test.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/InvokeFailureTest.cs Adds chained invoke failure integration test.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/InvokeReplayDeterminismTest.cs Adds replay determinism integration test.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/InvokeWithTenantIdTest.cs Adds tenant propagation integration test.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeHappyPathParentFunction/Function.cs Parent test workflow for happy path.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeHappyPathParentFunction/InvokeHappyPathParentFunction.csproj Project for happy-path parent function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeHappyPathParentFunction/Dockerfile Container definition for happy-path parent.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeHappyPathChildFunction/Function.cs Child test workflow for happy path.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeHappyPathChildFunction/InvokeHappyPathChildFunction.csproj Project for happy-path child function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeHappyPathChildFunction/Dockerfile Container definition for happy-path child.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeFailureParentFunction/Function.cs Parent test workflow for child failure handling.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeFailureParentFunction/InvokeFailureParentFunction.csproj Project for failure parent function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeFailureParentFunction/Dockerfile Container definition for failure parent.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeFailureChildFunction/Function.cs Child test workflow that fails intentionally.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeFailureChildFunction/InvokeFailureChildFunction.csproj Project for failure child function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeFailureChildFunction/Dockerfile Container definition for failure child.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeReplayDeterminismParentFunction/Function.cs Parent workflow for replay determinism scenario.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeReplayDeterminismParentFunction/InvokeReplayDeterminismParentFunction.csproj Project for replay parent function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeReplayDeterminismParentFunction/Dockerfile Container definition for replay parent.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeReplayDeterminismChildFunction/Function.cs Child workflow for replay echo scenario.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeReplayDeterminismChildFunction/InvokeReplayDeterminismChildFunction.csproj Project for replay child function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeReplayDeterminismChildFunction/Dockerfile Container definition for replay child.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeWithTenantIdFunction/Function.cs Parent workflow passing tenant ID.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeWithTenantIdFunction/InvokeWithTenantIdFunction.csproj Project for tenant parent function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeWithTenantIdFunction/Dockerfile Container definition for tenant parent.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeChildTenantFunction/Function.cs Child workflow for tenant scenario.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeChildTenantFunction/InvokeChildTenantFunction.csproj Project for tenant child function.
Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/InvokeChildTenantFunction/Dockerfile Container definition for tenant child.

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

Comment thread Libraries/src/Amazon.Lambda.DurableExecution/InvokeConfig.cs
Adds chained-function invocation to the .NET Durable Execution SDK.
InvokeAsync calls another durable function as a separate execution; the
caller suspends until the chained function completes, with the result
checkpointed for replay.

Public surface:
- IDurableContext.InvokeAsync<TPayload, TResult> (reflection + AOT-safe
  overloads with positional ICheckpointSerializer<TPayload> and
  ICheckpointSerializer<TResult>)
- InvokeConfig with Timeout (currently [Obsolete] - reserved for a future
  ChainedInvokeOptions wire field) and TenantId for tenant propagation
- Exception subclass tree: InvokeException base +
  InvokeFailedException, InvokeTimedOutException, InvokeStoppedException

Internal:
- InvokeOperation<TPayload, TResult> mirrors WaitOperation's sync-flush
  START + SuspendAndAwait pattern. Replay maps STARTED/PENDING to
  re-suspend; SUCCEEDED to cached deserialize; FAILED/TIMED_OUT/STOPPED
  to typed exception subclasses.
- ExecutionState.IsTerminalStatus now includes TimedOut (was missing).
- LambdaDurableServiceClient.MapFromSdkOperation now preserves ErrorData
  and StackTrace fields across all operation types (Step, ChildContext,
  ChainedInvoke). Pre-existing data-loss bug fix.
- Reuses TerminationReason.InvokePending and OperationSubTypes.Invoke
  from Wave 0.

Adds 38 unit tests + 4 integration tests covering happy path, failure
propagation, tenant-ID propagation, and replay determinism. Extends
DurableFunctionDeployment to support a downstream callee function with
cross-Lambda IAM.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@GarrettBeatty GarrettBeatty force-pushed the gcbeatty/durable-invoke branch from f3d103d to f0cf218 Compare May 29, 2026 16:44
/// <summary>
/// Maximum time to wait for the invoked function. Default (TimeSpan.Zero) means no timeout.
/// </summary>
public TimeSpan Timeout { get; set; } = TimeSpan.Zero;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

other sdks dont have this. this was a hallucination

@GarrettBeatty GarrettBeatty marked this pull request as ready for review May 29, 2026 17:01
@GarrettBeatty GarrettBeatty requested review from a team as code owners May 29, 2026 17:01
@GarrettBeatty GarrettBeatty requested review from normj and removed request for a team May 29, 2026 17:01
@GarrettBeatty GarrettBeatty requested a review from philasmar May 29, 2026 17:01
@@ -0,0 +1,182 @@
using System.IO;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

add license header

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

#2398 added in this separate PR instead

Comment thread Libraries/src/Amazon.Lambda.DurableExecution/InvokeConfig.cs
Comment thread Libraries/src/Amazon.Lambda.DurableExecution/InvokeException.cs
@@ -0,0 +1,7 @@
FROM public.ecr.aws/lambda/provided:al2023

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

add USER

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i dont think its worth fixing its just integration tests and the rest of them are like this

Comment thread Libraries/test/Amazon.Lambda.DurableExecution.Tests/ConfigTests.cs
@GarrettBeatty GarrettBeatty requested a review from philasmar May 29, 2026 18:28
Copy link
Copy Markdown
Member

@normj normj left a comment

Choose a reason for hiding this comment

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

PR looks good, i just had a comment about using .NET 10 for test projects instead of .NET 8. I'm guessing once we get the .NET managed runtime in the allow list for durable functions you might want to rework the test projects then to not be custom runtime container builds. So I'm okay if you want to retarget to .NET 10 as part of that work.

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I might have missed this in other PRs but can we make all test projects target .NET 10? We only have 6 months till .NET 8 goes out of support.

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.

5 participants