From c4e5589ea8e1ea837dd1847c1a4e67eab354913d Mon Sep 17 00:00:00 2001 From: Frank Chen Date: Wed, 2 Sep 2026 17:39:41 +0000 Subject: [PATCH 1/2] test(DurableExecution): add incremental parallel conformance handlers --- .../Conformance/README.md | 2 +- .../parallel/ParallelEarlyStart/Function.cs | 44 ++++++++++++++++ .../ParallelEarlyStart.csproj | 19 +++++++ .../ParallelTypedBranches/Function.cs | 52 +++++++++++++++++++ .../ParallelTypedBranches.csproj | 19 +++++++ .../Conformance/template_parallel.yaml | 36 +++++++++++++ 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/Function.cs create mode 100644 Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/ParallelEarlyStart.csproj create mode 100644 Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/Function.cs create mode 100644 Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/ParallelTypedBranches.csproj diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md index d4ce87efd..acb4e5d87 100644 --- a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md @@ -53,7 +53,7 @@ All nine suites are implemented (one handler project per requirement id): | `invoke` | 5-1 .. 5-15 | 15 (+2 target functions, +1 tenancy alias) | | `wait_for_condition` | 6-1 .. 6-13 | 13 | | `wait_for_callback` | 7-1 .. 7-15 | 15 | -| `parallel` | 8-1 .. 8-22 (8-15 n/a) | 21 | +| `parallel` | 8-1 .. 8-24 (8-15 n/a) | 23 | | `map` | 9-1 .. 9-18 (9-14 n/a) | 17 | A few requirement ids have no .NET handler because the SDK intentionally lacks diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/Function.cs b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/Function.cs new file mode 100644 index 000000000..cb32a40ca --- /dev/null +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/Function.cs @@ -0,0 +1,44 @@ +// 8-24: Parallel branch starts before registration is sealed +using Amazon.Lambda.Core; +using Amazon.Lambda.DurableExecution; +using Amazon.Lambda.RuntimeSupport; +using Amazon.Lambda.Serialization.SystemTextJson; + +namespace ParallelEarlyStart; + +public class Function +{ + public static async Task Main(string[] args) + { + var handler = new Function(); + var serializer = new DefaultLambdaJsonSerializer(); + using var handlerWrapper = HandlerWrapper.GetHandlerWrapper(handler.Handler, serializer); + using var bootstrap = new LambdaBootstrap(handlerWrapper); + await bootstrap.RunAsync(); + } + + public Task Handler( + DurableExecutionInvocationInput input, ILambdaContext context) + => DurableFunction.WrapAsync>(Workflow, input, context); + + private async Task> Workflow(object? input, IDurableContext context) + { + string firstResult; + IParallelBranch second; + + await using (var parallel = context.CreateParallel( + name: "early-start", + config: new ParallelConfig { MaxConcurrency = 1 })) + { + IParallelBranch first = parallel.BranchAsync( + "first", (_, _) => Task.FromResult("ready")); + firstResult = await first; + + second = parallel.BranchAsync( + "second", (_, _) => Task.FromResult(firstResult + "-second")); + await parallel.CompleteAsync(); + } + + return new List { firstResult, await second }; + } +} diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/ParallelEarlyStart.csproj b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/ParallelEarlyStart.csproj new file mode 100644 index 000000000..4b354e178 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/ParallelEarlyStart.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + Exe + true + bootstrap + enable + enable + + + + + + + + + + diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/Function.cs b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/Function.cs new file mode 100644 index 000000000..48dfb1de1 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/Function.cs @@ -0,0 +1,52 @@ +// 8-23: Parallel with independently typed heterogeneous branch handles +using Amazon.Lambda.Core; +using Amazon.Lambda.DurableExecution; +using Amazon.Lambda.RuntimeSupport; +using Amazon.Lambda.Serialization.SystemTextJson; + +namespace ParallelTypedBranches; + +public class Function +{ + public static async Task Main(string[] args) + { + var handler = new Function(); + var serializer = new DefaultLambdaJsonSerializer(); + using var handlerWrapper = HandlerWrapper.GetHandlerWrapper(handler.Handler, serializer); + using var bootstrap = new LambdaBootstrap(handlerWrapper); + await bootstrap.RunAsync(); + } + + public Task Handler( + DurableExecutionInvocationInput input, ILambdaContext context) + => DurableFunction.WrapAsync>(Workflow, input, context); + + private async Task> Workflow(object? input, IDurableContext context) + { + IParallelBranch inventory; + IParallelBranch payment; + IParallelBranch> quote; + + await using (var parallel = context.CreateParallel( + name: "typed-branches", + config: new ParallelConfig { MaxConcurrency = 1 })) + { + inventory = parallel.BranchAsync( + "inventory", (_, _) => Task.FromResult("reserved")); + payment = parallel.BranchAsync( + "payment", (_, _) => Task.FromResult(200)); + quote = parallel.BranchAsync( + "quote", (_, _) => Task.FromResult(new Dictionary + { + ["currency"] = "USD" + })); + + await parallel.CompleteAsync(); + } + + string inventoryResult = await inventory; + int paymentResult = await payment; + Dictionary quoteResult = await quote; + return new List { inventoryResult, paymentResult, quoteResult }; + } +} diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/ParallelTypedBranches.csproj b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/ParallelTypedBranches.csproj new file mode 100644 index 000000000..4b354e178 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/ParallelTypedBranches.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + Exe + true + bootstrap + enable + enable + + + + + + + + + + diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml index 589382ca8..ea8b7e0f6 100644 --- a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml @@ -412,3 +412,39 @@ Resources: DurableConfig: RetentionPeriodInDays: 7 ExecutionTimeout: 300 + + ParallelTypedBranches: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: ["8-23"] + Metadata: + BuildMethod: makefile + Properties: + CodeUri: publish/ParallelTypedBranches/ + Handler: bootstrap + Description: Parallel with independently typed heterogeneous branch handles + Role: + Fn::GetAtt: + - DurableFunctionRole + - Arn + DurableConfig: + RetentionPeriodInDays: 7 + ExecutionTimeout: 300 + + ParallelEarlyStart: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: ["8-24"] + Metadata: + BuildMethod: makefile + Properties: + CodeUri: publish/ParallelEarlyStart/ + Handler: bootstrap + Description: Parallel branch completes before later branches are registered + Role: + Fn::GetAtt: + - DurableFunctionRole + - Arn + DurableConfig: + RetentionPeriodInDays: 7 + ExecutionTimeout: 300 From cfd1ca61d4812bf8e18453b65f5261a7b294a884 Mon Sep 17 00:00:00 2001 From: Frank Chen Date: Wed, 2 Sep 2026 18:20:39 +0000 Subject: [PATCH 2/2] test(DurableExecution): add dedicated static typing suite --- .../Conformance/README.md | 5 +- .../Conformance/scripts/build_examples.sh | 2 +- .../ParallelEarlyStart/Function.cs | 2 +- .../ParallelEarlyStart.csproj | 0 .../ParallelTypedBranches/Function.cs | 2 +- .../ParallelTypedBranches.csproj | 0 .../Conformance/template_parallel.yaml | 36 ---------- .../Conformance/template_static_typing.yaml | 68 +++++++++++++++++++ 8 files changed, 74 insertions(+), 41 deletions(-) rename Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/{parallel => static_typing}/ParallelEarlyStart/Function.cs (96%) rename Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/{parallel => static_typing}/ParallelEarlyStart/ParallelEarlyStart.csproj (100%) rename Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/{parallel => static_typing}/ParallelTypedBranches/Function.cs (96%) rename Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/{parallel => static_typing}/ParallelTypedBranches/ParallelTypedBranches.csproj (100%) create mode 100644 Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_static_typing.yaml diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md index acb4e5d87..7b83c82da 100644 --- a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/README.md @@ -42,7 +42,7 @@ Conformance/ ## Coverage -All nine suites are implemented (one handler project per requirement id): +All ten suites are implemented (one handler project per requirement id): | Suite | Ids | Handlers | |-------|-----|----------| @@ -53,8 +53,9 @@ All nine suites are implemented (one handler project per requirement id): | `invoke` | 5-1 .. 5-15 | 15 (+2 target functions, +1 tenancy alias) | | `wait_for_condition` | 6-1 .. 6-13 | 13 | | `wait_for_callback` | 7-1 .. 7-15 | 15 | -| `parallel` | 8-1 .. 8-24 (8-15 n/a) | 23 | +| `parallel` | 8-1 .. 8-22 (8-15 n/a) | 21 | | `map` | 9-1 .. 9-18 (9-14 n/a) | 17 | +| `static_typing` | 12-1 .. 12-2 | 2 | A few requirement ids have no .NET handler because the SDK intentionally lacks the feature they exercise (e.g. per-item / whole-result serdes slots in `map`); diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/scripts/build_examples.sh b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/scripts/build_examples.sh index 4ce59e368..6707491ab 100755 --- a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/scripts/build_examples.sh +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/scripts/build_examples.sh @@ -10,7 +10,7 @@ # ./build_examples.sh [operation...] # # Operations (default: every suite directory found next to the templates): -# step wait callback child invoke parallel map wait_for_callback wait_for_condition +# step wait callback child invoke parallel map static_typing wait_for_callback wait_for_condition # # Examples: # ./build_examples.sh step diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/Function.cs b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelEarlyStart/Function.cs similarity index 96% rename from Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/Function.cs rename to Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelEarlyStart/Function.cs index cb32a40ca..56f3fa9c4 100644 --- a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/Function.cs +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelEarlyStart/Function.cs @@ -1,4 +1,4 @@ -// 8-24: Parallel branch starts before registration is sealed +// 12-2: Parallel branch starts before registration is sealed using Amazon.Lambda.Core; using Amazon.Lambda.DurableExecution; using Amazon.Lambda.RuntimeSupport; diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/ParallelEarlyStart.csproj b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelEarlyStart/ParallelEarlyStart.csproj similarity index 100% rename from Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelEarlyStart/ParallelEarlyStart.csproj rename to Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelEarlyStart/ParallelEarlyStart.csproj diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/Function.cs b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelTypedBranches/Function.cs similarity index 96% rename from Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/Function.cs rename to Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelTypedBranches/Function.cs index 48dfb1de1..c4cc4b768 100644 --- a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/Function.cs +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelTypedBranches/Function.cs @@ -1,4 +1,4 @@ -// 8-23: Parallel with independently typed heterogeneous branch handles +// 12-1: Parallel with independently typed heterogeneous branch handles using Amazon.Lambda.Core; using Amazon.Lambda.DurableExecution; using Amazon.Lambda.RuntimeSupport; diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/ParallelTypedBranches.csproj b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelTypedBranches/ParallelTypedBranches.csproj similarity index 100% rename from Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/parallel/ParallelTypedBranches/ParallelTypedBranches.csproj rename to Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/static_typing/ParallelTypedBranches/ParallelTypedBranches.csproj diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml index ea8b7e0f6..589382ca8 100644 --- a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_parallel.yaml @@ -412,39 +412,3 @@ Resources: DurableConfig: RetentionPeriodInDays: 7 ExecutionTimeout: 300 - - ParallelTypedBranches: - Type: AWS::Serverless::Function - TestingMetadata: - TestDescription: ["8-23"] - Metadata: - BuildMethod: makefile - Properties: - CodeUri: publish/ParallelTypedBranches/ - Handler: bootstrap - Description: Parallel with independently typed heterogeneous branch handles - Role: - Fn::GetAtt: - - DurableFunctionRole - - Arn - DurableConfig: - RetentionPeriodInDays: 7 - ExecutionTimeout: 300 - - ParallelEarlyStart: - Type: AWS::Serverless::Function - TestingMetadata: - TestDescription: ["8-24"] - Metadata: - BuildMethod: makefile - Properties: - CodeUri: publish/ParallelEarlyStart/ - Handler: bootstrap - Description: Parallel branch completes before later branches are registered - Role: - Fn::GetAtt: - - DurableFunctionRole - - Arn - DurableConfig: - RetentionPeriodInDays: 7 - ExecutionTimeout: 300 diff --git a/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_static_typing.yaml b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_static_typing.yaml new file mode 100644 index 000000000..599898e05 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/Conformance/template_static_typing.yaml @@ -0,0 +1,68 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Durable Execution Conformance Test Examples - .NET (Static Typing) +Globals: + Function: + Runtime: dotnet8 + Timeout: 60 + MemorySize: 512 + +Resources: + DurableFunctionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: DurableExecutionPolicy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - lambda:CheckpointDurableExecution + - lambda:GetDurableExecutionState + Resource: '*' + + ParallelTypedBranches: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: ["12-1"] + Metadata: + BuildMethod: makefile + Properties: + CodeUri: publish/ParallelTypedBranches/ + Handler: bootstrap + Description: Parallel with independently typed heterogeneous branch handles + Role: + Fn::GetAtt: + - DurableFunctionRole + - Arn + DurableConfig: + RetentionPeriodInDays: 7 + ExecutionTimeout: 300 + + ParallelEarlyStart: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: ["12-2"] + Metadata: + BuildMethod: makefile + Properties: + CodeUri: publish/ParallelEarlyStart/ + Handler: bootstrap + Description: Parallel branch completes before later branches are registered + Role: + Fn::GetAtt: + - DurableFunctionRole + - Arn + DurableConfig: + RetentionPeriodInDays: 7 + ExecutionTimeout: 300