diff --git a/docs/spec/map.md b/docs/spec/map.md
index 87f549e54..ee63796f7 100644
--- a/docs/spec/map.md
+++ b/docs/spec/map.md
@@ -290,7 +290,7 @@ import software.amazon.awssdk.services.lambda.model.ContextOptions;
import software.amazon.awssdk.services.lambda.model.Operation;
import software.amazon.awssdk.services.lambda.model.OperationAction;
import software.amazon.awssdk.services.lambda.model.OperationUpdate;
-import software.amazon.lambda.durable.CompletionConfig;
+import software.amazon.lambda.durable.config.CompletionConfig;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.TypeToken;
import software.amazon.lambda.durable.model.CompletionReason;
@@ -480,8 +480,8 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import software.amazon.lambda.durable.DurableContext;
-import software.amazon.lambda.durable.MapConfig;
-import software.amazon.lambda.durable.MapFunction;
+import software.amazon.lambda.durable.config.MapConfig;
+import software.amazon.lambda.durable.DurableContext.MapFunction;
import software.amazon.lambda.durable.TypeToken;
import software.amazon.lambda.durable.model.BatchResult;
import software.amazon.lambda.durable.model.OperationSubType;
@@ -900,8 +900,8 @@ package software.amazon.lambda.durable.operation;
import java.util.List;
import software.amazon.lambda.durable.DurableContext;
-import software.amazon.lambda.durable.MapConfig;
-import software.amazon.lambda.durable.MapFunction;
+import software.amazon.lambda.durable.config.MapConfig;
+import software.amazon.lambda.durable.DurableContext.MapFunction;
import software.amazon.lambda.durable.model.BatchResult;
import software.amazon.lambda.durable.model.OperationSubType;
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/CallbackExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/CallbackExample.java
index 31c9b784a..29697f277 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/CallbackExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/CallbackExample.java
@@ -3,9 +3,9 @@
package software.amazon.lambda.durable.examples;
import java.time.Duration;
-import software.amazon.lambda.durable.CallbackConfig;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
+import software.amazon.lambda.durable.config.CallbackConfig;
/**
* Example demonstrating callback operations for external system integration.
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/ComplexMapExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/ComplexMapExample.java
index e7ba2726d..ce010e575 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/ComplexMapExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/ComplexMapExample.java
@@ -5,10 +5,10 @@
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
-import software.amazon.lambda.durable.CompletionConfig;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.MapConfig;
+import software.amazon.lambda.durable.config.CompletionConfig;
+import software.amazon.lambda.durable.config.MapConfig;
/**
* Example demonstrating advanced map features: wait operations inside branches, error handling, and early termination.
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/CustomPollingExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/CustomPollingExample.java
index 9aa0c68ca..aab698e97 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/CustomPollingExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/CustomPollingExample.java
@@ -6,7 +6,7 @@
import software.amazon.lambda.durable.DurableConfig;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.InvokeConfig;
+import software.amazon.lambda.durable.config.InvokeConfig;
import software.amazon.lambda.durable.retry.JitterStrategy;
import software.amazon.lambda.durable.retry.PollingStrategies;
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/ErrorHandlingExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/ErrorHandlingExample.java
index e74a60b9b..cc58ef42e 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/ErrorHandlingExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/ErrorHandlingExample.java
@@ -6,8 +6,8 @@
import org.slf4j.LoggerFactory;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.StepConfig;
-import software.amazon.lambda.durable.StepSemantics;
+import software.amazon.lambda.durable.config.StepConfig;
+import software.amazon.lambda.durable.config.StepSemantics;
import software.amazon.lambda.durable.exception.StepFailedException;
import software.amazon.lambda.durable.exception.StepInterruptedException;
import software.amazon.lambda.durable.retry.RetryStrategies;
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/GenericInputOutputExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/GenericInputOutputExample.java
index 47bacf9c2..e996b4835 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/GenericInputOutputExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/GenericInputOutputExample.java
@@ -9,8 +9,8 @@
import org.slf4j.LoggerFactory;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.StepConfig;
import software.amazon.lambda.durable.TypeToken;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.retry.RetryStrategies;
/**
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/GenericTypesExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/GenericTypesExample.java
index b4edd512e..1b10f5e55 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/GenericTypesExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/GenericTypesExample.java
@@ -9,8 +9,8 @@
import org.slf4j.LoggerFactory;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.StepConfig;
import software.amazon.lambda.durable.TypeToken;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.retry.RetryStrategies;
/**
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/RetryInProcessExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/RetryInProcessExample.java
index 79644bed6..ee5a8e3de 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/RetryInProcessExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/RetryInProcessExample.java
@@ -9,7 +9,7 @@
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableFuture;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.StepConfig;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.retry.JitterStrategy;
import software.amazon.lambda.durable.retry.RetryStrategies;
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/SimpleInvokeExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/SimpleInvokeExample.java
index 4c976de64..e54f5418b 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/SimpleInvokeExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/SimpleInvokeExample.java
@@ -4,7 +4,7 @@
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.InvokeConfig;
+import software.amazon.lambda.durable.config.InvokeConfig;
/**
* Simple example demonstrating basic invoke execution with the Durable Execution SDK.
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastExample.java
index 22d2201ae..e08b55f99 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastExample.java
@@ -8,7 +8,7 @@
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableFuture;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.StepConfig;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.retry.RetryStrategies;
/**
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastInProcessExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastInProcessExample.java
index a8454eaae..f6103c4c6 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastInProcessExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/WaitAtLeastInProcessExample.java
@@ -8,7 +8,7 @@
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableFuture;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.StepConfig;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.retry.RetryStrategies;
/**
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/WaitExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/WaitExample.java
index 7385fd48a..988262f4b 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/WaitExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/WaitExample.java
@@ -4,6 +4,7 @@
import java.time.Duration;
import software.amazon.lambda.durable.DurableContext;
+import software.amazon.lambda.durable.DurableFuture;
import software.amazon.lambda.durable.DurableHandler;
/**
@@ -31,15 +32,26 @@ public String handleRequest(GreetingRequest input, DurableContext context) {
context.wait(null, Duration.ofSeconds(10));
// Step 2: Continue processing
- var continued =
- context.step("continue-processing", String.class, stepCtx -> started + " - continued after 10s");
+ var continued = context.stepAsync("continue-processing", String.class, stepCtx -> {
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return started + " - continued after 10s";
+ });
- // Wait 5 seconds
- context.wait(null, Duration.ofSeconds(5));
+ // Wait at most seconds
+ var wait5seconds = context.runInChildContextAsync("wait-5-seconds", String.class, ctx -> {
+ ctx.wait("wait-5-seconds", Duration.ofSeconds(5));
+
+ return started + " - waited 5 seconds";
+ });
+
+ var step2 = DurableFuture.anyOf(continued, wait5seconds);
// Step 3: Complete
- var result =
- context.step("complete-processing", String.class, stepCtx -> continued + " - completed after 5s more");
+ var result = context.step("complete-processing", String.class, stepCtx -> step2 + " - completed after 5s more");
return result;
}
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelExample.java
index a13005c7b..35c91f37c 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelExample.java
@@ -7,7 +7,8 @@
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableFuture;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.ParallelConfig;
+import software.amazon.lambda.durable.ParallelDurableFuture;
+import software.amazon.lambda.durable.config.ParallelConfig;
import software.amazon.lambda.durable.model.ParallelResult;
/**
@@ -21,8 +22,8 @@
*
A final step combines the results into a summary
*
*
- * The {@link software.amazon.lambda.durable.ParallelContext} implements {@link AutoCloseable}, so try-with-resources
- * guarantees {@code join()} is called even if an exception occurs.
+ *
The {@link ParallelDurableFuture} implements {@link AutoCloseable}, so try-with-resources guarantees
+ * {@code join()} is called even if an exception occurs.
*/
public class ParallelExample extends DurableHandler {
@@ -54,9 +55,9 @@ public Output handleRequest(Input input, DurableContext context) {
ParallelResult parallelResult = parallel.get();
logger.info(
"Parallel complete: total={}, succeeded={}, failed={}",
- parallelResult.getTotalBranches(),
- parallelResult.getSucceededBranches(),
- parallelResult.getFailedBranches());
+ parallelResult.size(),
+ parallelResult.succeeded(),
+ parallelResult.failed());
var results = futures.stream().map(DurableFuture::get).toList();
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExample.java
index b498db8de..8b7c97bba 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExample.java
@@ -7,8 +7,9 @@
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableFuture;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.ParallelConfig;
-import software.amazon.lambda.durable.StepConfig;
+import software.amazon.lambda.durable.config.CompletionConfig;
+import software.amazon.lambda.durable.config.ParallelConfig;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.model.ParallelResult;
import software.amazon.lambda.durable.retry.RetryStrategies;
@@ -25,7 +26,7 @@
public class ParallelFailureToleranceExample
extends DurableHandler {
- public record Input(List services, int toleratedFailures, int minSuccessful) {}
+ public record Input(List services, Integer toleratedFailures, Integer minSuccessful) {}
public record Output(int succeeded, int failed) {}
@@ -35,8 +36,7 @@ public Output handleRequest(Input input, DurableContext context) {
logger.info("Starting parallel execution with toleratedFailureCount={}", input.toleratedFailures());
var config = ParallelConfig.builder()
- .minSuccessful(input.minSuccessful())
- .toleratedFailureCount(input.toleratedFailures())
+ .completionConfig(new CompletionConfig(input.minSuccessful, input.toleratedFailures, null))
.build();
var futures = new ArrayList>(input.services().size());
@@ -65,12 +65,12 @@ public Output handleRequest(Input input, DurableContext context) {
ParallelResult parallelResult = parallel.get();
logger.info(
"Parallel complete: succeeded={}, failed={}, status={}",
- parallelResult.getSucceededBranches(),
- parallelResult.getFailedBranches(),
- parallelResult.getCompletionStatus().isSucceeded() ? "succeeded" : "failed");
+ parallelResult.succeeded(),
+ parallelResult.failed(),
+ parallelResult.completionStatus().isSucceeded() ? "succeeded" : "failed");
- var succeeded = parallelResult.getSucceededBranches();
- var failed = parallelResult.getFailedBranches();
+ var succeeded = parallelResult.succeeded();
+ var failed = parallelResult.failed();
logger.info("Completed: {} succeeded, {} failed", succeeded, failed);
return new Output(succeeded, failed);
diff --git a/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelWithWaitExample.java b/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelWithWaitExample.java
index 63bbee21d..a7c0e3ac2 100644
--- a/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelWithWaitExample.java
+++ b/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelWithWaitExample.java
@@ -8,7 +8,7 @@
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableFuture;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.ParallelConfig;
+import software.amazon.lambda.durable.config.ParallelConfig;
import software.amazon.lambda.durable.model.ParallelResult;
/**
@@ -68,6 +68,6 @@ public Output handleRequest(Input input, DurableContext context) {
logger.info("All {} notifications delivered", deliveries.size());
// Test replay
context.wait("wait for finalization", Duration.ofSeconds(5));
- return new Output(deliveries, result.getSucceededBranches(), result.getFailedBranches());
+ return new Output(deliveries, result.succeeded(), result.failed());
}
}
diff --git a/examples/src/test/java/software/amazon/lambda/durable/examples/CloudBasedIntegrationTest.java b/examples/src/test/java/software/amazon/lambda/durable/examples/CloudBasedIntegrationTest.java
index c0e703cc4..639fa23cf 100644
--- a/examples/src/test/java/software/amazon/lambda/durable/examples/CloudBasedIntegrationTest.java
+++ b/examples/src/test/java/software/amazon/lambda/durable/examples/CloudBasedIntegrationTest.java
@@ -171,7 +171,8 @@ void testWaitExample() {
var finalResult = result.getResult(String.class);
assertNotNull(finalResult);
assertTrue(finalResult.contains("Started processing for TestUser"));
- assertTrue(finalResult.contains("continued after 10s"));
+ assertFalse(finalResult.contains("continued after 10s"));
+ assertTrue(finalResult.contains("waited 5 seconds"));
assertTrue(finalResult.contains("completed after 5s more"));
assertNotNull(runner.getOperation("start-processing"));
diff --git a/examples/src/test/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExampleTest.java b/examples/src/test/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExampleTest.java
index 7d4dd72d1..f1518e2ac 100644
--- a/examples/src/test/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExampleTest.java
+++ b/examples/src/test/java/software/amazon/lambda/durable/examples/parallel/ParallelFailureToleranceExampleTest.java
@@ -17,7 +17,7 @@ void succeedsWhenFailuresAreWithinTolerance() {
var runner = LocalDurableTestRunner.create(ParallelFailureToleranceExample.Input.class, handler);
// 2 good services, 1 bad — toleratedFailureCount=1 so the parallel op still succeeds
- var input = new ParallelFailureToleranceExample.Input(List.of("svc-a", "bad-svc-b", "svc-c"), 1, -1);
+ var input = new ParallelFailureToleranceExample.Input(List.of("svc-a", "bad-svc-b", "svc-c"), 1, null);
var result = runner.runUntilComplete(input);
assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus());
@@ -32,7 +32,7 @@ void succeedsWhenAllBranchesSucceed() {
var handler = new ParallelFailureToleranceExample();
var runner = LocalDurableTestRunner.create(ParallelFailureToleranceExample.Input.class, handler);
- var input = new ParallelFailureToleranceExample.Input(List.of("svc-a", "svc-b", "svc-c"), 2, -1);
+ var input = new ParallelFailureToleranceExample.Input(List.of("svc-a", "svc-b", "svc-c"), 2, null);
var result = runner.runUntilComplete(input);
assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus());
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CallbackIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CallbackIntegrationTest.java
index 8ab42779f..b253425ee 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CallbackIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CallbackIntegrationTest.java
@@ -10,6 +10,7 @@
import software.amazon.awssdk.services.lambda.model.ErrorObject;
import software.amazon.awssdk.services.lambda.model.OperationStatus;
import software.amazon.awssdk.services.lambda.model.OperationType;
+import software.amazon.lambda.durable.config.CallbackConfig;
import software.amazon.lambda.durable.exception.CallbackFailedException;
import software.amazon.lambda.durable.exception.CallbackTimeoutException;
import software.amazon.lambda.durable.model.ExecutionStatus;
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomConfigIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomConfigIntegrationTest.java
index a6dd8a78a..e6f02ed75 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomConfigIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomConfigIntegrationTest.java
@@ -11,6 +11,7 @@
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.lambda.LambdaClient;
import software.amazon.lambda.durable.client.LambdaDurableFunctionsClient;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.serde.JacksonSerDes;
import software.amazon.lambda.durable.serde.SerDes;
import software.amazon.lambda.durable.testing.LocalDurableTestRunner;
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomSerDesIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomSerDesIntegrationTest.java
index 6c966e214..336c81f5c 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomSerDesIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/CustomSerDesIntegrationTest.java
@@ -7,6 +7,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.serde.JacksonSerDes;
import software.amazon.lambda.durable.serde.SerDes;
import software.amazon.lambda.durable.testing.LocalDurableTestRunner;
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/ExceptionIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/ExceptionIntegrationTest.java
index 8dd811dd9..5445a4f3d 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/ExceptionIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/ExceptionIntegrationTest.java
@@ -8,6 +8,8 @@
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
+import software.amazon.lambda.durable.config.StepConfig;
+import software.amazon.lambda.durable.config.StepSemantics;
import software.amazon.lambda.durable.exception.StepInterruptedException;
import software.amazon.lambda.durable.model.ExecutionStatus;
import software.amazon.lambda.durable.retry.RetryStrategies;
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/MapIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/MapIntegrationTest.java
index 3bbd8c569..7788cc4a1 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/MapIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/MapIntegrationTest.java
@@ -9,9 +9,11 @@
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
+import software.amazon.lambda.durable.config.CompletionConfig;
+import software.amazon.lambda.durable.config.MapConfig;
import software.amazon.lambda.durable.model.ConcurrencyCompletionStatus;
import software.amazon.lambda.durable.model.ExecutionStatus;
-import software.amazon.lambda.durable.model.MapResultItem;
+import software.amazon.lambda.durable.model.MapResult;
import software.amazon.lambda.durable.testing.LocalDurableTestRunner;
class MapIntegrationTest {
@@ -535,8 +537,10 @@ void testMapWithAllSuccessfulCompletionConfig_stopsOnFirstFailure() {
assertEquals("OK1", result.getResult(0));
assertNotNull(result.getError(1));
// Items after the failure should be NOT_STARTED
- assertEquals(MapResultItem.Status.NOT_STARTED, result.getItem(2).status());
- assertEquals(MapResultItem.Status.NOT_STARTED, result.getItem(3).status());
+ assertEquals(
+ MapResult.MapResultItem.Status.SKIPPED, result.getItem(2).status());
+ assertEquals(
+ MapResult.MapResultItem.Status.SKIPPED, result.getItem(3).status());
return "done";
});
@@ -873,7 +877,9 @@ void testMapWithNullResults() {
assertTrue(result.allSucceeded());
assertEquals(3, result.size());
for (int i = 0; i < result.size(); i++) {
- assertEquals(MapResultItem.Status.SUCCEEDED, result.getItem(i).status());
+ assertEquals(
+ MapResult.MapResultItem.Status.SUCCEEDED,
+ result.getItem(i).status());
assertNull(result.getResult(i));
assertNull(result.getError(i));
}
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/StepSemanticsIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/StepSemanticsIntegrationTest.java
index 34f9f87be..1b3b67409 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/StepSemanticsIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/StepSemanticsIntegrationTest.java
@@ -6,6 +6,8 @@
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
+import software.amazon.lambda.durable.config.StepConfig;
+import software.amazon.lambda.durable.config.StepSemantics;
import software.amazon.lambda.durable.model.ExecutionStatus;
import software.amazon.lambda.durable.retry.RetryStrategies;
import software.amazon.lambda.durable.testing.LocalDurableTestRunner;
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/WaitForConditionIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/WaitForConditionIntegrationTest.java
index 105dd6a88..689c25b9f 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/WaitForConditionIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/WaitForConditionIntegrationTest.java
@@ -10,6 +10,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
+import software.amazon.lambda.durable.config.WaitForConditionConfig;
import software.amazon.lambda.durable.model.ExecutionStatus;
import software.amazon.lambda.durable.model.WaitForConditionResult;
import software.amazon.lambda.durable.retry.JitterStrategy;
diff --git a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/retry/RetryIntegrationTest.java b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/retry/RetryIntegrationTest.java
index 2debf140f..259d8c653 100644
--- a/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/retry/RetryIntegrationTest.java
+++ b/sdk-integration-tests/src/test/java/software/amazon/lambda/durable/retry/RetryIntegrationTest.java
@@ -9,7 +9,7 @@
import org.junit.jupiter.api.Test;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
-import software.amazon.lambda.durable.StepConfig;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.model.ExecutionStatus;
import software.amazon.lambda.durable.testing.LocalDurableTestRunner;
diff --git a/sdk-testing/src/test/java/software/amazon/lambda/durable/testing/SkipTimeTest.java b/sdk-testing/src/test/java/software/amazon/lambda/durable/testing/SkipTimeTest.java
index cdaf87f3c..8fa2f591d 100644
--- a/sdk-testing/src/test/java/software/amazon/lambda/durable/testing/SkipTimeTest.java
+++ b/sdk-testing/src/test/java/software/amazon/lambda/durable/testing/SkipTimeTest.java
@@ -7,7 +7,7 @@
import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
-import software.amazon.lambda.durable.StepConfig;
+import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.model.ExecutionStatus;
import software.amazon.lambda.durable.retry.RetryStrategies;
diff --git a/sdk/src/main/java/software/amazon/lambda/durable/CallbackConfig.java b/sdk/src/main/java/software/amazon/lambda/durable/CallbackConfig.java
index 9cb859aee..0d63a5c29 100644
--- a/sdk/src/main/java/software/amazon/lambda/durable/CallbackConfig.java
+++ b/sdk/src/main/java/software/amazon/lambda/durable/CallbackConfig.java
@@ -2,109 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable;
-import java.time.Duration;
-import software.amazon.lambda.durable.serde.SerDes;
-import software.amazon.lambda.durable.util.ParameterValidator;
-
-/** Configuration for callback operations. */
+/** @deprecated use {@link software.amazon.lambda.durable.config.CallbackConfig} instead. */
+@Deprecated
public class CallbackConfig {
- private final Duration timeout;
- private final Duration heartbeatTimeout;
- private final SerDes serDes;
-
- private CallbackConfig(Builder builder) {
- this.timeout = builder.timeout;
- this.heartbeatTimeout = builder.heartbeatTimeout;
- this.serDes = builder.serDes;
- }
-
- /**
- * Returns the maximum duration to wait for the callback to complete.
- *
- * @return the timeout duration, or null if not specified
- */
- public Duration timeout() {
- return timeout;
- }
-
- /**
- * Returns the maximum duration between heartbeats before the callback is considered failed.
- *
- * @return the heartbeat timeout duration, or null if not specified
- */
- public Duration heartbeatTimeout() {
- return heartbeatTimeout;
- }
-
- /** Returns the custom serializer for this callback, or null if not specified (uses default SerDes). */
- public SerDes serDes() {
- return serDes;
- }
-
- /** Creates a new builder with default values. */
- public static Builder builder() {
- return new Builder(null, null, null);
- }
-
- /** Creates a new builder pre-populated with this config's values. */
- public Builder toBuilder() {
- return new Builder(timeout, heartbeatTimeout, serDes);
- }
-
- /** Builder for {@link CallbackConfig}. */
- public static class Builder {
- private Duration timeout;
- private Duration heartbeatTimeout;
- private SerDes serDes;
-
- private Builder(Duration timeout, Duration heartbeatTimeout, SerDes serDes) {
- this.timeout = timeout;
- this.heartbeatTimeout = heartbeatTimeout;
- this.serDes = serDes;
- }
-
- /**
- * Sets the maximum duration to wait for the callback to complete before timing out.
- *
- * @param timeout the timeout duration
- * @return this builder for method chaining
- */
- public Builder timeout(Duration timeout) {
- ParameterValidator.validateOptionalDuration(timeout, "Callback timeout");
- this.timeout = timeout;
- return this;
- }
-
- /**
- * Sets the maximum duration between heartbeats before the callback is considered failed.
- *
- * @param heartbeatTimeout the heartbeat timeout duration
- * @return this builder for method chaining
- */
- public Builder heartbeatTimeout(Duration heartbeatTimeout) {
- ParameterValidator.validateOptionalDuration(heartbeatTimeout, "Heartbeat timeout");
- this.heartbeatTimeout = heartbeatTimeout;
- return this;
- }
-
- /**
- * Sets a custom serializer for the callback.
- *
- * If not specified, the callback will use the default SerDes configured for the handler. This allows
- * per-callback customization of serialization behavior, useful for callbacks that need special handling (e.g.,
- * custom date formats, encryption, compression).
- *
- * @param serDes the custom serializer to use, or null to use the default
- * @return this builder for method chaining
- */
- public Builder serDes(SerDes serDes) {
- this.serDes = serDes;
- return this;
- }
-
- /** Builds the {@link CallbackConfig} instance. */
- public CallbackConfig build() {
- return new CallbackConfig(this);
- }
+ /** @deprecated use {@link software.amazon.lambda.durable.config.CallbackConfig#builder()} instead. */
+ @Deprecated
+ public static software.amazon.lambda.durable.config.CallbackConfig.Builder builder() {
+ return new software.amazon.lambda.durable.config.CallbackConfig.Builder(null, null, null);
}
}
diff --git a/sdk/src/main/java/software/amazon/lambda/durable/DurableConfig.java b/sdk/src/main/java/software/amazon/lambda/durable/DurableConfig.java
index e97843360..b83c7598c 100644
--- a/sdk/src/main/java/software/amazon/lambda/durable/DurableConfig.java
+++ b/sdk/src/main/java/software/amazon/lambda/durable/DurableConfig.java
@@ -267,7 +267,7 @@ public static final class Builder {
private PollingStrategy pollingStrategy;
private Duration checkpointDelay;
- private Builder() {}
+ public Builder() {}
/**
* Sets a custom LambdaClient for production use. Use this method to customize the AWS SDK client with specific
diff --git a/sdk/src/main/java/software/amazon/lambda/durable/DurableContext.java b/sdk/src/main/java/software/amazon/lambda/durable/DurableContext.java
index 79ebda106..2f652232f 100644
--- a/sdk/src/main/java/software/amazon/lambda/durable/DurableContext.java
+++ b/sdk/src/main/java/software/amazon/lambda/durable/DurableContext.java
@@ -8,6 +8,14 @@
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
+import software.amazon.lambda.durable.config.CallbackConfig;
+import software.amazon.lambda.durable.config.InvokeConfig;
+import software.amazon.lambda.durable.config.MapConfig;
+import software.amazon.lambda.durable.config.ParallelConfig;
+import software.amazon.lambda.durable.config.RunInChildContextConfig;
+import software.amazon.lambda.durable.config.StepConfig;
+import software.amazon.lambda.durable.config.WaitForCallbackConfig;
+import software.amazon.lambda.durable.config.WaitForConditionConfig;
import software.amazon.lambda.durable.context.BaseContext;
import software.amazon.lambda.durable.model.MapResult;
import software.amazon.lambda.durable.model.WaitForConditionResult;
@@ -25,7 +33,9 @@ public interface DurableContext extends BaseContext {
* @param func the function to execute, receiving a {@link StepContext}
* @return the step result
*/
- T step(String name, Class resultType, Function func);
+ default T step(String name, Class resultType, Function func) {
+ return step(name, TypeToken.get(resultType), func, StepConfig.builder().build());
+ }
/**
* Executes a durable step with the given name and configuration, blocking until it completes.
@@ -37,7 +47,9 @@ public interface DurableContext extends BaseContext {
* @param config the step configuration (retry strategy, semantics, custom SerDes)
* @return the step result
*/
- T step(String name, Class resultType, Function func, StepConfig config);
+ default T step(String name, Class resultType, Function func, StepConfig config) {
+ return stepAsync(name, resultType, func, config).get();
+ }
/**
* Executes a durable step using a {@link TypeToken} for generic result types, blocking until it completes.
@@ -48,7 +60,9 @@ public interface DurableContext extends BaseContext {
* @param func the function to execute, receiving a {@link StepContext}
* @return the step result
*/
- T step(String name, TypeToken resultType, Function func);
+ default T step(String name, TypeToken resultType, Function func) {
+ return step(name, resultType, func, StepConfig.builder().build());
+ }
/**
* Executes a durable step using a {@link TypeToken} and configuration, blocking until it completes.
@@ -60,7 +74,9 @@ public interface DurableContext extends BaseContext {
* @param config the step configuration (retry strategy, semantics, custom SerDes)
* @return the step result
*/
- T step(String name, TypeToken resultType, Function func, StepConfig config);
+ default T step(String name, TypeToken resultType, Function func, StepConfig config) {
+ return stepAsync(name, resultType, func, config).get();
+ }
/**
* Asynchronously executes a durable step, returning a {@link DurableFuture} that can be composed or blocked on.
@@ -71,7 +87,10 @@ public interface DurableContext extends BaseContext {
* @param func the function to execute, receiving a {@link StepContext}
* @return a future representing the step result
*/
- DurableFuture stepAsync(String name, Class resultType, Function func);
+ default DurableFuture stepAsync(String name, Class resultType, Function func) {
+ return stepAsync(
+ name, TypeToken.get(resultType), func, StepConfig.builder().build());
+ }
/**
* Asynchronously executes a durable step using custom configuration.
@@ -84,7 +103,10 @@ public interface DurableContext extends BaseContext {
* @param config the step configuration (retry strategy, semantics, custom SerDes)
* @return a future representing the step result
*/
- DurableFuture stepAsync(String name, Class resultType, Function func, StepConfig config);
+ default DurableFuture stepAsync(
+ String name, Class resultType, Function func, StepConfig config) {
+ return stepAsync(name, TypeToken.get(resultType), func, config);
+ }
/**
* Asynchronously executes a durable step using a {@link TypeToken} for generic result types.
@@ -97,7 +119,9 @@ public interface DurableContext extends BaseContext {
* @param func the function to execute, receiving a {@link StepContext}
* @return a future representing the step result
*/
- DurableFuture stepAsync(String name, TypeToken resultType, Function func);
+ default DurableFuture stepAsync(String name, TypeToken resultType, Function func) {
+ return stepAsync(name, resultType, func, StepConfig.builder().build());
+ }
/**
* Asynchronously executes a durable step using a {@link TypeToken} and custom configuration.
@@ -114,29 +138,60 @@ public interface DurableContext extends BaseContext {
DurableFuture stepAsync(
String name, TypeToken resultType, Function func, StepConfig config);
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- T step(String name, Class resultType, Supplier func);
-
+ default T step(String name, Class resultType, Supplier func) {
+ return stepAsync(
+ name,
+ TypeToken.get(resultType),
+ func,
+ StepConfig.builder().build())
+ .get();
+ }
+
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- T step(String name, Class resultType, Supplier func, StepConfig config);
+ default T step(String name, Class resultType, Supplier func, StepConfig config) {
+ // Simply delegate to stepAsync and block on the result
+ return stepAsync(name, TypeToken.get(resultType), func, config).get();
+ }
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- T step(String name, TypeToken resultType, Supplier func);
+ default T step(String name, TypeToken resultType, Supplier func) {
+ return stepAsync(name, resultType, func, StepConfig.builder().build()).get();
+ }
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- T step(String name, TypeToken resultType, Supplier func, StepConfig config);
+ default T step(String name, TypeToken resultType, Supplier func, StepConfig config) {
+ return stepAsync(name, resultType, func, config).get();
+ }
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- DurableFuture stepAsync(String name, Class resultType, Supplier func);
+ default DurableFuture stepAsync(String name, Class resultType, Supplier func) {
+ return stepAsync(
+ name, TypeToken.get(resultType), func, StepConfig.builder().build());
+ }
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- DurableFuture stepAsync(String name, Class resultType, Supplier func, StepConfig config);
+ default DurableFuture stepAsync(String name, Class resultType, Supplier func, StepConfig config) {
+ return stepAsync(name, TypeToken.get(resultType), func, config);
+ }
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- DurableFuture stepAsync(String name, TypeToken resultType, Supplier func);
+ default DurableFuture stepAsync(String name, TypeToken resultType, Supplier func) {
+ return stepAsync(name, resultType, func, StepConfig.builder().build());
+ }
+ /** @deprecated use the variants accepting StepContext instead */
@Deprecated
- DurableFuture stepAsync(String name, TypeToken resultType, Supplier func, StepConfig config);
+ default DurableFuture stepAsync(String name, TypeToken resultType, Supplier func, StepConfig config) {
+ return stepAsync(name, resultType, stepContext -> func.get(), config);
+ }
/**
* Suspends execution for the specified duration without consuming compute resources.
@@ -148,7 +203,9 @@ DurableFuture stepAsync(
* @param duration the duration to wait
* @return always {@code null}
*/
- Void wait(String name, Duration duration);
+ default Void wait(String name, Duration duration) {
+ return waitAsync(name, duration).get();
+ }
/**
* Asynchronously suspends execution for the specified duration.
@@ -173,26 +230,59 @@ DurableFuture stepAsync(
* @param resultType the result class for deserialization
* @return the invocation result
*/
- T invoke(String name, String functionName, U payload, Class resultType);
+ default T invoke(String name, String functionName, U payload, Class resultType) {
+ return invokeAsync(
+ name,
+ functionName,
+ payload,
+ TypeToken.get(resultType),
+ InvokeConfig.builder().build())
+ .get();
+ }
/** Invokes another Lambda function with custom configuration, blocking until the result is available. */
- T invoke(String name, String functionName, U payload, Class resultType, InvokeConfig config);
+ default T invoke(String name, String functionName, U payload, Class resultType, InvokeConfig config) {
+ return invokeAsync(name, functionName, payload, TypeToken.get(resultType), config)
+ .get();
+ }
/** Invokes another Lambda function using a {@link TypeToken} for generic result types, blocking until complete. */
- T invoke(String name, String functionName, U payload, TypeToken resultType);
+ default T invoke(String name, String functionName, U payload, TypeToken resultType) {
+ return invokeAsync(
+ name,
+ functionName,
+ payload,
+ resultType,
+ InvokeConfig.builder().build())
+ .get();
+ }
/** Invokes another Lambda function using a {@link TypeToken} and custom configuration, blocking until complete. */
- T invoke(String name, String functionName, U payload, TypeToken resultType, InvokeConfig config);
+ default T invoke(String name, String functionName, U payload, TypeToken resultType, InvokeConfig config) {
+ return invokeAsync(name, functionName, payload, resultType, config).get();
+ }
/** Invokes another Lambda function using a {@link TypeToken} and custom configuration, blocking until complete. */
- DurableFuture invokeAsync(
- String name, String functionName, U payload, Class resultType, InvokeConfig config);
+ default DurableFuture invokeAsync(
+ String name, String functionName, U payload, Class resultType, InvokeConfig config) {
+ return invokeAsync(name, functionName, payload, TypeToken.get(resultType), config);
+ }
/** Asynchronously invokes another Lambda function, returning a {@link DurableFuture}. */
- DurableFuture invokeAsync(String name, String functionName, U payload, Class resultType);
+ default DurableFuture invokeAsync(String name, String functionName, U payload, Class resultType) {
+ return invokeAsync(
+ name,
+ functionName,
+ payload,
+ TypeToken.get(resultType),
+ InvokeConfig.builder().build());
+ }
/** Asynchronously invokes another Lambda function using a {@link TypeToken} for generic result types. */
- DurableFuture invokeAsync(String name, String functionName, U payload, TypeToken resultType);
+ default DurableFuture invokeAsync(String name, String functionName, U payload, TypeToken resultType) {
+ return invokeAsync(
+ name, functionName, payload, resultType, InvokeConfig.builder().build());
+ }
/**
* Asynchronously invokes another Lambda function using a {@link TypeToken} and custom configuration.
@@ -212,13 +302,20 @@ DurableFuture invokeAsync(
String name, String functionName, U payload, TypeToken resultType, InvokeConfig config);
/** Creates a callback with custom configuration. */
- DurableCallbackFuture createCallback(String name, Class resultType, CallbackConfig config);
+ default DurableCallbackFuture createCallback(String name, Class resultType, CallbackConfig config) {
+ return createCallback(name, TypeToken.get(resultType), config);
+ }
/** Creates a callback using a {@link TypeToken} for generic result types. */
- DurableCallbackFuture createCallback(String name, TypeToken resultType);
+ default DurableCallbackFuture createCallback(String name, TypeToken resultType) {
+ return createCallback(name, resultType, CallbackConfig.builder().build());
+ }
/** Creates a callback with default configuration. */
- DurableCallbackFuture createCallback(String name, Class resultType);
+ default DurableCallbackFuture createCallback(String name, Class resultType) {
+ return createCallback(
+ name, TypeToken.get(resultType), CallbackConfig.builder().build());
+ }
/**
* Creates a callback operation that suspends execution until an external system completes it.
@@ -246,48 +343,188 @@ DurableFuture invokeAsync(
* @param func the function to execute, receiving a child {@link DurableContext}
* @return the child context result
*/
- T runInChildContext(String name, Class resultType, Function func);
+ default T runInChildContext(String name, Class resultType, Function func) {
+ return runInChildContextAsync(
+ name,
+ TypeToken.get(resultType),
+ func,
+ RunInChildContextConfig.builder().build())
+ .get();
+ }
/**
* Runs a function in a child context using a {@link TypeToken} for generic result types, blocking until complete.
*/
- T runInChildContext(String name, TypeToken resultType, Function func);
-
- /** Asynchronously runs a function in a child context, returning a {@link DurableFuture}. */
- DurableFuture runInChildContextAsync(String name, Class resultType, Function func);
+ default T runInChildContext(String name, TypeToken resultType, Function func) {
+ return runInChildContextAsync(
+ name,
+ resultType,
+ func,
+ RunInChildContextConfig.builder().build())
+ .get();
+ }
- /** Asynchronously runs a function in a child context using a {@link TypeToken} for generic result types. */
- DurableFuture runInChildContextAsync(String name, TypeToken resultType, Function func);
-
- MapResult map(String name, Collection items, Class resultType, MapFunction function);
-
- MapResult map(
- String name, Collection items, Class resultType, MapFunction function, MapConfig config);
+ /**
+ * Runs a function in a child context, blocking until it completes.
+ *
+ * Child contexts provide isolated operation ID namespaces, allowing nested workflows to be composed without ID
+ * collisions. On replay, the child context's operations are replayed independently.
+ *
+ * @param name the operation name within this context
+ * @param resultType the result class for deserialization
+ * @param func the function to execute, receiving a child {@link DurableContext}
+ * @return the DurableFuture of the child context result
+ */
+ default DurableFuture runInChildContextAsync(
+ String name, Class resultType, Function func) {
+ return runInChildContextAsync(
+ name,
+ TypeToken.get(resultType),
+ func,
+ RunInChildContextConfig.builder().build());
+ }
- MapResult map(String name, Collection items, TypeToken resultType, MapFunction function);
+ /**
+ * Runs a function in a child context, blocking until it completes.
+ *
+ * Child contexts provide isolated operation ID namespaces, allowing nested workflows to be composed without ID
+ * collisions. On replay, the child context's operations are replayed independently.
+ *
+ * @param name the operation name within this context
+ * @param resultType the result class for deserialization
+ * @param func the function to execute, receiving a child {@link DurableContext}
+ * @return the DurableFuture of the child context result
+ */
+ default DurableFuture runInChildContextAsync(
+ String name, TypeToken resultType, Function func) {
+ return runInChildContextAsync(
+ name, resultType, func, RunInChildContextConfig.builder().build());
+ }
- MapResult map(
- String name, Collection items, TypeToken resultType, MapFunction function, MapConfig config);
+ /**
+ * Runs a function in a child context, blocking until it completes.
+ *
+ * Child contexts provide isolated operation ID namespaces, allowing nested workflows to be composed without ID
+ * collisions. On replay, the child context's operations are replayed independently.
+ *
+ * @param the result type
+ * @param name the unique operation name within this context
+ * @param resultType the result class for deserialization
+ * @param func the function to execute, receiving a child {@link DurableContext}
+ * @return the child context result
+ */
+ default T runInChildContext(
+ String name, Class resultType, Function func, RunInChildContextConfig config) {
+ return runInChildContextAsync(name, TypeToken.get(resultType), func, config)
+ .get();
+ }
- DurableFuture> mapAsync(
- String name, Collection items, Class resultType, MapFunction function);
+ /**
+ * Runs a function in a child context, blocking until it completes.
+ *
+ * Child contexts provide isolated operation ID namespaces, allowing nested workflows to be composed without ID
+ * collisions. On replay, the child context's operations are replayed independently.
+ *
+ * @param name the operation name within this context
+ * @param resultType the result class for deserialization
+ * @param func the function to execute, receiving a child {@link DurableContext}
+ * @param config the configuration for the child context
+ * @return the child context result
+ */
+ default T runInChildContext(
+ String name, TypeToken resultType, Function func, RunInChildContextConfig config) {
+ return runInChildContextAsync(name, resultType, func, config).get();
+ }
- DurableFuture> mapAsync(
- String name, Collection items, Class resultType, MapFunction function, MapConfig config);
+ /**
+ * Runs a function in a child context, blocking until it completes.
+ *
+ * Child contexts provide isolated operation ID namespaces, allowing nested workflows to be composed without ID
+ * collisions. On replay, the child context's operations are replayed independently.
+ *
+ * @param name the operation name within this context
+ * @param resultType the result class for deserialization
+ * @param func the function to execute, receiving a child {@link DurableContext}
+ * @param config the configuration for the child context
+ * @return the DurableFuture wrapping the child context result
+ */
+ default DurableFuture runInChildContextAsync(
+ String name, Class resultType, Function func, RunInChildContextConfig config) {
+ return runInChildContextAsync(name, TypeToken.get(resultType), func, config);
+ }
- DurableFuture> mapAsync(
- String name, Collection items, TypeToken resultType, MapFunction function);
+ /**
+ * Runs a function in a child context, blocking until it completes.
+ *
+ * Child contexts provide isolated operation ID namespaces, allowing nested workflows to be composed without ID
+ * collisions. On replay, the child context's operations are replayed independently.
+ *
+ * @param name the operation name within this context
+ * @param resultType the result class for deserialization
+ * @param func the function to execute, receiving a child {@link DurableContext}
+ * @param config the configuration for the child context
+ * @return the DurableFuture wrapping the child context result
+ */
+ DurableFuture runInChildContextAsync(
+ String name, TypeToken resultType, Function