Added Java SDK support to the AWS Lambda durable functions skill#112
Added Java SDK support to the AWS Lambda durable functions skill#112smoell wants to merge 4 commits intoawslabs:mainfrom
Conversation
| **Java:** | ||
|
|
||
| ```java | ||
| // Use DurableFuture.allOf() for parallel heterogeneous operations |
There was a problem hiding this comment.
Java SDK now supports parallel natively. See the examples here: https://github.com/aws/aws-durable-execution-sdk-java/blob/main/examples/src/main/java/software/amazon/lambda/durable/examples/parallel/ParallelExample.java
There was a problem hiding this comment.
- Updated
concurrent-operations.mdlines 138-167 - Added native
ctx.parallel()implementation usingParallelDurableFuture(verified from SDK source) - Implemented correct pattern based on actual SDK API:
- Call
ctx.parallel(name, ParallelConfig)returnsParallelDurableFuture - Use try-with-resources (implements
AutoCloseable) - Call
parallel.branch(name, type, func)for each branch - returnsDurableFuture<T> - Branches complete automatically when try block exits (calls
close()which callsget()) - Access individual results with
branchFuture.get()
- Call
| s -> shippingService.createShipment(event.getAddress(), event.getItems())); | ||
|
|
||
| return new OrderResult(true, shipment.getOrderId()); | ||
| } catch (Exception e) { |
There was a problem hiding this comment.
This would also catch SuspendExecutionException, which doesn't mean Order failed
There was a problem hiding this comment.
- Changed
catch (Exception e)tocatch (DurableExecutionException e)in error-handling.md lines 305-316 - Added import for
DurableExecutionException - Added explanatory comment: "Catch only business logic exceptions - not SuspendExecutionException. SuspendExecutionException is used internally for checkpointing and should propagate."
- Updated inner catch block to also use
DurableExecutionException
| - **Steps**: `ctx.step("name", ResultType.class, stepCtx -> operation())` - type must be specified | ||
| - **Wait**: `ctx.wait("name", Duration.ofSeconds(n))` - always name waits for debugging | ||
| - **Generic Types**: Use `TypeToken` for generic types like `List<T>`: `ctx.step("name", new TypeToken<List<User>>() {}, stepCtx -> ...)` | ||
| - **Exceptions**: `StepFailedException`, `StepInterruptedException`, `CallbackTimeoutException`, `CallbackFailedException` |
There was a problem hiding this comment.
This isn't a complete list. Will agents be able to discover them all with this hint or we have to list all the operations and exceptions here?
There was a problem hiding this comment.
Completed Java exception types in SKILL.md
| **Implementation approach:** | ||
|
|
||
| 1. Use `waitForCallback` (TypeScript) or `wait_for_callback` (Python) with a timeout configuration set in the config argument | ||
| 1. Use `waitForCallback` (TypeScript), `wait_for_callback` (Python), or `ctx.waitForCallback` (Java) with a timeout configuration set in the config argument |
There was a problem hiding this comment.
Why does the java reference include the ctx object while the others don't?
| In TypeScript, native setTimeout (and patterns like Promise.race using it) will fail during execution replays. To create a reliable timeout that persists across execution (expands over multi invocations), always use the timeout parameter provided by waitForCallback or waitForCondition. | ||
|
|
||
| **Java considerations:** | ||
| Java does not have an equivalent to Promise.race for local timeouts within a single invocation. Always use the timeout configuration in `CallbackConfig` or `WaitForConditionConfig` for reliable cross-invocation timeouts. |
There was a problem hiding this comment.
Always use the timeout configuration in CallbackConfigorWaitForConditionConfig for reliable cross-invocation timeouts. -> is this specifically a Java consideration?
There was a problem hiding this comment.
Java does not have an equivalent to Promise.race
Java does have something equivalent: DurableFuture.anyOf
There was a problem hiding this comment.
- Added
DurableFuture.anyOf()documentation to advanced-error-handling.md - Added new "Java equivalent - DurableFuture.anyOf" section after the TypeScript Promise.race section
|
|
||
| **Exception types by language:** | ||
|
|
||
| - **TypeScript**: Timeout errors thrown from `waitForCallback` or `waitForCondition` |
There was a problem hiding this comment.
Should this include the error types like the others?
|
|
||
| - **TypeScript**: Timeout errors thrown from `waitForCallback` or `waitForCondition` | ||
| - **Python**: `CallbackError` for callback failures | ||
| - **Java**: `CallbackTimeoutException`, `CallbackFailedException`, `WaitForConditionFailedException` |
There was a problem hiding this comment.
Should this have categorization of the exception types?
| **Exception types by language:** | ||
|
|
||
| - **TypeScript**: Timeout errors thrown from `waitForCallback` or `waitForCondition` | ||
| - **Python**: `CallbackError` for callback failures |
| │ └── com/example/ | ||
| │ └── MyHandlerTest.java # Tests with DurableFunctionTestRunner | ||
| ├── infrastructure/ | ||
| │ └── template.yaml # SAM/CloudFormation |
|
|
||
| ```xml | ||
| <properties> | ||
| <aws-durable-execution-sdk-java.version>LATEST</aws-durable-execution-sdk-java.version> |
There was a problem hiding this comment.
This will expose customers to major version bumps and release candidates, won't it?
|
|
||
| ### Java | ||
|
|
||
| - [ ] Add SDK dependencies to `pom.xml` with version property set to `LATEST` |
|
|
||
| - [ ] Add SDK dependencies to `pom.xml` with version property set to `LATEST` | ||
| - [ ] Set Java compiler source/target to 17+ in `pom.xml` | ||
| - [ ] Create handler class extending `DurableHandler<TInput, TOutput>` |
| var f1 = ctx.stepAsync("batch-1", BatchResult.class, | ||
| s -> ctx.invoke("invoke-1", childArn, event.getBatches().get(0), BatchResult.class)); | ||
| var f2 = ctx.stepAsync("batch-2", BatchResult.class, | ||
| s -> ctx.invoke("invoke-2", childArn, event.getBatches().get(1), BatchResult.class)); |
There was a problem hiding this comment.
I don't think you can start any durable operation in a step, including invoke in this case
|
|
||
| var approved = childCtx.waitForCallback("approval", ApprovalData.class, | ||
| (callbackId, s) -> sendApproval(item, callbackId), | ||
| CallbackConfig.builder().timeout(Duration.ofHours(24)).build()); |
There was a problem hiding this comment.
waitForCallback accepts WaitForCallbackConfig, not CallbackConfig.
There was a problem hiding this comment.
Changed lines 779-782 in advanced-patterns.md
| var id = UUID.randomUUID().toString(); // Different UUID each time | ||
| var timestamp = System.currentTimeMillis(); // Different timestamp each time | ||
| var random = Math.random(); // Different random number | ||
| ctx.step("save", Void.class, s -> { saveData(id, timestamp); return null; }); |
There was a problem hiding this comment.
What's wrong with this step operation?
| .initialDelay(Duration.ofSeconds(5)) | ||
| .maxDelay(Duration.ofSeconds(30)) | ||
| .backoffRate(1.5))) | ||
| .shouldContinuePolling(state -> !"completed".equals(state.getStatus())) |
There was a problem hiding this comment.
There is no shouldContinuePolling configuration in WaitForConditionConfig. The decision is made inside the user function directly when returning a new state.
| boolean shouldContinue = state.getData() == null || !state.getData().isReady(); | ||
| return shouldContinue | ||
| ? WaitForConditionResult.continuePolling(delay) | ||
| : WaitForConditionResult.stopPolling(); |
There was a problem hiding this comment.
same here. In Java, the decision is made in the user function directly
| "Reject: " + approvalUrl + "?callback=" + callbackId + "&action=reject" | ||
| )); | ||
| }, | ||
| CallbackConfig.builder().timeout(Duration.ofHours(48)).build()); |
There was a problem hiding this comment.
Same here. waitForCallback accepts WaitForCallbackConfig
|
Fixed open issues |
Add comprehensive Java examples to all reference documentation sections
Related
Ensures complete language coverage for the Lambda Durable Functions skill across TypeScript, Python, and
Java, enabling developers to use the skill regardless of their runtime preference.
Changes
Documentation Updates:
Added missing Python and Java examples to 17 sections across 4 reference files:
concurrent-operations.md (10 sections):
wait-operations.md (4 sections):
advanced-patterns.md (2 sections):
getting-started.md (1 section):
Key Patterns Documented:
MapConfig,CompletionConfig,WaitForConditionConfig,StepSemantics, customSerDesimplementations
MapConfig,CompletionConfig,WaitForConditionConfig,WaitStrategies,custom
SerDes<T>interface,DurableFutureasync operationsAcknowledgment
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this
contribution, under the terms of the project
license.