diff --git a/packages/aws-durable-execution-sdk-js-examples/ADDING_EXAMPLES.md b/packages/aws-durable-execution-sdk-js-examples/ADDING_EXAMPLES.md index e935db18..50ff30dd 100644 --- a/packages/aws-durable-execution-sdk-js-examples/ADDING_EXAMPLES.md +++ b/packages/aws-durable-execution-sdk-js-examples/ADDING_EXAMPLES.md @@ -87,21 +87,20 @@ Create a test file in the same directory: ```typescript import { handler } from "./{example-name}"; -import { createTests } from "../../shared/test-helper"; // For nested: "../../../shared/test-helper" +import { createTests } from "../../../utils/test-helper"; // For standalone: "../../utils/test-helper" createTests({ - name: "my-example test", - functionName: "{example-name}", handler, - tests: (runner) => { - it("should return expected result", async () => { + tests: (runner, { assertEventSignatures }) => { + it("should execute successfully with expected result and operations", async () => { const execution = await runner.run(); - expect(execution.getResult()).toEqual("example result"); - }); - it("should execute correct number of operations", async () => { - const execution = await runner.run(); + // Multiple assertions on the same execution + expect(execution.getResult()).toEqual("example result"); expect(execution.getOperations()).toHaveLength(2); // adjust based on your example + + // REQUIRED: Must call assertEventSignatures for every test + assertEventSignatures(execution); }); }, }); @@ -172,38 +171,147 @@ The `createTests` helper provides a unified interface: ```typescript createTests({ - name: string; // Test suite name - functionName: string; // Must match handler filename (without .ts) - handler: Function; // The handler function to test - invocationType?: string; // Optional: 'RequestResponse' | 'Event' - tests: (runner, isCloud) => void; // Test definitions + handler: DurableLambdaHandler; // The handler function to test + tests: TestCallback; // Test definitions + invocationType?: InvocationType; // Optional: 'RequestResponse' | 'Event' + localRunnerConfig?: LocalDurableTestRunnerSetupParameters; // Optional local test config }); ``` Inside `tests`, you have access to: - `runner`: Either `LocalDurableTestRunner` or `CloudDurableTestRunner` -- `isCloud`: Boolean indicating if running against real Lambda +- `testHelper`: Object containing: + - `assertEventSignatures`: **Required** function to validate execution history + - `isTimeSkipping`: Boolean indicating if time is being skipped in tests + - `isCloud`: Boolean indicating if running against real Lambda + - `functionNameMap`: Helper for resolving function names in tests + +## Event Signature Validation with `assertEventSignatures` + +**IMPORTANT**: Every test **MUST** call `assertEventSignatures(execution)` at the end. This validates that the execution produces the expected sequence of durable execution events. + +### How it Works + +1. **First Run**: When you first create a test, run it with `GENERATE_HISTORY=true` to create the history file: + + ```bash + GENERATE_HISTORY=true npm test + ``` + +2. **History File Creation**: This generates a `.history.json` file next to your test containing the expected event signatures. + +3. **Subsequent Runs**: Normal test runs compare the actual events against the stored history file. + +### Example Usage + +```typescript +createTests({ + handler, + tests: (runner, { assertEventSignatures }) => { + it("should complete workflow successfully", async () => { + const execution = await runner.run(); + + // Your test assertions + expect(execution.getResult()).toEqual("completed"); + expect(execution.getOperations()).toHaveLength(3); + + // REQUIRED: Validate event signatures + assertEventSignatures(execution); + }); + + it("should handle callback operations", async () => { + const callbackOp = runner.getOperation("my-callback"); + const executionPromise = runner.run(); + + await callbackOp.waitForData(); + await callbackOp.sendCallbackSuccess("result"); + + const execution = await executionPromise; + expect(execution.getResult()).toEqual("result"); + + // REQUIRED: Validate event signatures + assertEventSignatures(execution); + }); + }, +}); +``` + +### Multiple History Files + +For tests with multiple scenarios, you can create separate history files: + +```typescript +it("should handle success case", async () => { + const execution = await runner.run({ scenario: "success" }); + expect(execution.getResult()).toBe("success"); + + // Creates/uses example-name-success.history.json + assertEventSignatures(execution, "success"); +}); + +it("should handle failure case", async () => { + const execution = await runner.run({ scenario: "failure" }); + expect(execution.getError()).toBeDefined(); + + // Creates/uses example-name-failure.history.json + assertEventSignatures(execution, "failure"); +}); +``` ### Common Test Patterns ```typescript -tests: (runner, isCloud) => { - it("should return expected result", async () => { +tests: (runner, { assertEventSignatures, isCloud, isTimeSkipping }) => { + // Combine tests with identical setup (same runner.run() call) + it("should execute successfully with expected result and operations", async () => { const execution = await runner.run(); + + // Multiple assertions on the same execution expect(execution.getResult()).toEqual(expectedValue); - }); + expect(execution.getOperations()).toHaveLength(3); - it("should execute operations in order", async () => { - const execution = await runner.run(); + // Check operations in order const ops = execution.getOperations(); - expect(ops[0].name).toBe("step-1"); - expect(ops[1].name).toBe("step-2"); + expect(ops[0].getName()).toBe("step-1"); + expect(ops[1].getName()).toBe("step-2"); + + // REQUIRED + assertEventSignatures(execution); + }); + + // Separate test only when setup is different (different parameters, callbacks, etc.) + it("should handle callback operations", async () => { + const callbackOp = runner.getOperation("my-callback"); + const executionPromise = runner.run(); + + // Wait for callback to start + await callbackOp.waitForData(); + + // Send callback result + await callbackOp.sendCallbackSuccess("callback-result"); + + const execution = await executionPromise; + expect(execution.getResult()).toContain("callback-result"); + + // REQUIRED + assertEventSignatures(execution); }); - it("should execute correct number of operations", async () => { + // Environment-specific tests with different setups + it("should behave differently in cloud vs local", async () => { const execution = await runner.run(); - expect(execution.getOperations()).toHaveLength(3); + + if (isCloud) { + // Cloud-specific assertions + expect(execution.getInvocations().length).toBeGreaterThan(1); + } else { + // Local-specific assertions + expect(isTimeSkipping).toBe(true); + } + + // REQUIRED + assertEventSignatures(execution); }); }; ``` @@ -213,6 +321,9 @@ tests: (runner, isCloud) => { - [ ] Created example file in appropriate directory structure - [ ] Created test file in same directory - [ ] Used correct import paths for test-helper and types +- [ ] Added `assertEventSignatures` parameter to test callback +- [ ] Called `assertEventSignatures(execution)` in every test +- [ ] Generated history files with `GENERATE_HISTORY=true npm test` - [ ] Local tests pass (`npm test`) - [ ] Integration tests pass in CI/CD @@ -231,6 +342,31 @@ sam local execution history $DURABLE_EXECUTION_ARN ## Troubleshooting -**Test not found in integration run:** +### assertEventSignatures Issues + +**Error: "assertEventSignature was not called for test [name]"** + +- You forgot to call `assertEventSignatures(execution)` in one or more of your tests +- Make sure every `it()` test calls this function + +**Error: "History file [...].history.json does not exist"** + +- Run the test with `GENERATE_HISTORY=true npm test` to create the history file +- Make sure the file is committed to your repository + +**Error: Event signature mismatch** + +- The execution produced different events than expected +- If this is intentional (you changed the function), regenerate the history with `GENERATE_HISTORY=true npm test` +- If not intentional, check your function logic for unintended changes + +**TypeError: testResult.getHistoryEvents is not a function** + +- You're passing the wrong variable to `assertEventSignatures` +- Pass the `execution` result from `runner.run()`, not `execution.getResult()` + +### Test Setup Issues + +**Tests timing out:** -- Verify `functionName` in test matches the example name +- For local tests with time skipping disabled: make sure step retries are not longer than the timeout diff --git a/packages/aws-durable-execution-sdk-js-examples/jest.config.integration.js b/packages/aws-durable-execution-sdk-js-examples/jest.config.integration.js index f151e506..bdf3ea1b 100644 --- a/packages/aws-durable-execution-sdk-js-examples/jest.config.integration.js +++ b/packages/aws-durable-execution-sdk-js-examples/jest.config.integration.js @@ -8,5 +8,5 @@ module.exports = { testMatch: ["**/src/examples/**/*.test.ts"], testTimeout: 120000, testNamePattern: "cloud", - bail: true, + // bail: true, }; diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/concurrent/create-callback-concurrent.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/concurrent/create-callback-concurrent.history.json new file mode 100644 index 00000000..96d5bf22 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/concurrent/create-callback-concurrent.history.json @@ -0,0 +1,124 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "ef61112a-8abb-4cb1-b4eb-e84df17b3eff", + "EventTimestamp": "2025-12-11T22:10:27.253Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "api-call-1", + "EventTimestamp": "2025-12-11T22:10:27.286Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImY5MmRjZDMzLTE1NTEtNDg2OS04ZDhmLTVkY2E1ZmMzNjM0YyIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiYmMxM2U4MjYtNmIyZC00MzQyLThjOTYtNDg1MmM1NDhjNTk2In0=", + "Timeout": 300, + "Input": {} + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "c81e728d9d4c2f63", + "Name": "api-call-2", + "EventTimestamp": "2025-12-11T22:10:27.307Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImY5MmRjZDMzLTE1NTEtNDg2OS04ZDhmLTVkY2E1ZmMzNjM0YyIsIm9wZXJhdGlvbklkIjoiYzgxZTcyOGQ5ZDRjMmY2MyIsInRva2VuIjoiY2EyOWZmYWQtZDMyMi00YmQ1LTlkNGMtNGY4ZjAxYTk2MjI1In0=", + "Timeout": 300, + "Input": {} + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 4, + "Id": "eccbc87e4b5ce2fe", + "Name": "api-call-3", + "EventTimestamp": "2025-12-11T22:10:27.327Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImY5MmRjZDMzLTE1NTEtNDg2OS04ZDhmLTVkY2E1ZmMzNjM0YyIsIm9wZXJhdGlvbklkIjoiZWNjYmM4N2U0YjVjZTJmZSIsInRva2VuIjoiYjAzNTJkYTItMjlhNy00NjViLWI1ZDItNzdjMDgxOTI1MzBlIn0=", + "Timeout": 300, + "Input": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-11T22:10:27.347Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T22:10:27.253Z", + "EndTimestamp": "2025-12-11T22:10:27.347Z", + "Error": {}, + "RequestId": "87f8f141-1f5f-456f-b2ce-332246be3e33" + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 6, + "Id": "c81e728d9d4c2f63", + "Name": "api-call-2", + "EventTimestamp": "2025-12-11T22:10:27.431Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"id\":2,\"data\":\"second\"}" + } + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 7, + "Id": "c4ca4238a0b92382", + "Name": "api-call-1", + "EventTimestamp": "2025-12-11T22:10:27.432Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"id\":1,\"data\":\"first\"}" + } + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 8, + "Id": "eccbc87e4b5ce2fe", + "Name": "api-call-3", + "EventTimestamp": "2025-12-11T22:10:27.432Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"id\":3,\"data\":\"third\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-11T22:10:27.453Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T22:10:27.452Z", + "EndTimestamp": "2025-12-11T22:10:27.453Z", + "Error": {}, + "RequestId": "9f51c6e9-d21b-4ba7-be12-2ced22ae2f29" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "ef61112a-8abb-4cb1-b4eb-e84df17b3eff", + "EventTimestamp": "2025-12-11T22:10:27.453Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"results\":[\"{\\\"id\\\":1,\\\"data\\\":\\\"first\\\"}\",\"{\\\"id\\\":2,\\\"data\\\":\\\"second\\\"}\",\"{\\\"id\\\":3,\\\"data\\\":\\\"third\\\"}\"],\"allCompleted\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/concurrent/create-callback-concurrent.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/concurrent/create-callback-concurrent.test.ts index 037a15f9..6dfd13d4 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/concurrent/create-callback-concurrent.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/concurrent/create-callback-concurrent.test.ts @@ -9,7 +9,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle multiple concurrent callback operations", async () => { // Get all callback operations const callback1 = runner.getOperation("api-call-1"); @@ -25,22 +25,27 @@ createTests({ callback3.waitForData(WaitingOperationStatus.STARTED), ]); + // Wait a bit to ensure invocations complete (TODO: add a waitForInvocation to testing lib) + await new Promise((resolve) => setTimeout(resolve, 100)); + // Complete callbacks in different order const callbackResult2 = JSON.stringify({ id: 2, data: "second", }); - await callback2.sendCallbackSuccess(callbackResult2); const callbackResult1 = JSON.stringify({ id: 1, data: "first", }); - await callback1.sendCallbackSuccess(callbackResult1); const callbackResult3 = JSON.stringify({ id: 3, data: "third", }); - await callback3.sendCallbackSuccess(callbackResult3); + await Promise.all([ + callback2.sendCallbackSuccess(callbackResult2), + callback1.sendCallbackSuccess(callbackResult1), + callback3.sendCallbackSuccess(callbackResult3), + ]); const result = await executionPromise; @@ -57,6 +62,10 @@ createTests({ (op) => op.getType() === OperationType.CALLBACK, ), ).toBe(true); + + assertEventSignatures(result, undefined, { + invocationCompletedDifference: 1, + }); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/failures/create-callback-failures.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/failures/create-callback-failures.history.json new file mode 100644 index 00000000..c39b63ba --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/failures/create-callback-failures.history.json @@ -0,0 +1,82 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "489831c7-988e-47fc-b01e-aea2d3d9916f", + "EventTimestamp": "2025-12-10T00:15:10.670Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"shouldCatchError\":false}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failing-operation", + "EventTimestamp": "2025-12-10T00:15:10.702Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImU3ODA2MWMwLTY1OTgtNDlhZi1iNTMzLTM1OWQwMjA3ZDc4MiIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiNTA4ZjUwMjUtN2JiNC00OTUwLTk2MGItNTMzZDJhOTU2MmNkIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackFailed", + "SubType": "Callback", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "Name": "failing-operation", + "EventTimestamp": "2025-12-10T00:15:10.703Z", + "CallbackFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "External API failure", + "ErrorType": "APIException" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:10.762Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.670Z", + "EndTimestamp": "2025-12-10T00:15:10.762Z", + "Error": {}, + "RequestId": "ec711523-276b-4d18-b7a9-a96053f58caa" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:10.784Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.783Z", + "EndTimestamp": "2025-12-10T00:15:10.784Z", + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "External API failure" + } + }, + "RequestId": "562069c6-e606-4403-83b4-da93a5ab332c" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 6, + "Id": "489831c7-988e-47fc-b01e-aea2d3d9916f", + "EventTimestamp": "2025-12-10T00:15:10.784Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "External API failure" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/failures/create-callback-failures.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/failures/create-callback-failures.test.ts index 91c5f98a..654b594e 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/failures/create-callback-failures.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/failures/create-callback-failures.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle callback operations with failure", async () => { const callbackOperation = runner.getOperation("failing-operation"); @@ -32,6 +32,8 @@ createTests({ errorType: "CallbackError", stackTrace: undefined, }); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/heartbeat/create-callback-heartbeat.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/heartbeat/create-callback-heartbeat.history.json new file mode 100644 index 00000000..499c4c50 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/heartbeat/create-callback-heartbeat.history.json @@ -0,0 +1,72 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "70381ad4-7099-443f-8d6e-e7160b89ef72", + "EventTimestamp": "2025-12-10T00:12:25.149Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"isCloud\":false}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "long-running-task", + "EventTimestamp": "2025-12-10T00:12:25.154Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjA3MzU0YzM3LTlkMzAtNDkzNC04NGRjLTkzMjVlNjRlZWRkMiIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiZDI4Njc4ZjctMTBmNS00NTY2LThlMjctYjczM2Y3NDdhY2U3In0=", + "HeartbeatTimeout": 1, + "Input": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 3, + "EventTimestamp": "2025-12-10T00:12:25.205Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:25.149Z", + "EndTimestamp": "2025-12-10T00:12:25.205Z", + "Error": {}, + "RequestId": "d0f3a9b7-5015-48bb-b73d-5b405f4f4103" + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 4, + "Id": "c4ca4238a0b92382", + "Name": "long-running-task", + "EventTimestamp": "2025-12-10T00:12:26.358Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"processed\":1000,\"status\":\"completed\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:12:26.360Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:26.360Z", + "EndTimestamp": "2025-12-10T00:12:26.360Z", + "Error": {}, + "RequestId": "071ab60f-7282-4e3b-bedf-1477ade7d430" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "70381ad4-7099-443f-8d6e-e7160b89ef72", + "EventTimestamp": "2025-12-10T00:12:26.361Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"longTaskResult\":\"{\\\"processed\\\":1000,\\\"status\\\":\\\"completed\\\"}\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/heartbeat/create-callback-heartbeat.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/heartbeat/create-callback-heartbeat.test.ts index 0c0a709a..bfedcce6 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/heartbeat/create-callback-heartbeat.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/heartbeat/create-callback-heartbeat.test.ts @@ -5,7 +5,7 @@ import { InvocationType } from "@aws-sdk/client-lambda"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner, { isCloud }) => { + tests: (runner, { isCloud, assertEventSignatures }) => { it("should handle callback heartbeats during long-running tasks", async () => { const callbackOperation = runner.getOperation("long-running-task"); @@ -37,6 +37,8 @@ createTests({ expect(result.getResult()).toEqual({ longTaskResult: callbackResult, }); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/mixed-ops/create-callback-mixed-ops.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/mixed-ops/create-callback-mixed-ops.history.json new file mode 100644 index 00000000..f0d83f84 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/mixed-ops/create-callback-mixed-ops.history.json @@ -0,0 +1,129 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "420929c0-50c3-484b-9430-85d4f7b5d5a4", + "EventTimestamp": "2025-12-12T00:05:31.127Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "fetch-data", + "EventTimestamp": "2025-12-12T00:05:31.133Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "Name": "fetch-data", + "EventTimestamp": "2025-12-12T00:05:31.133Z", + "StepSucceededDetails": { + "Result": { + "Payload": "{\"userId\":123,\"name\":\"John Doe\"}" + }, + "RetryDetails": {} + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 4, + "Id": "c81e728d9d4c2f63", + "Name": "process-user", + "EventTimestamp": "2025-12-12T00:05:31.136Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjYyMWJiNmVkLTgxYTItNGJjZC1iM2IzLTcxYjljYmIxNDY0MSIsIm9wZXJhdGlvbklkIjoiYzgxZTcyOGQ5ZDRjMmY2MyIsInRva2VuIjoiY2U1NDg5ZTYtZjhjNi00YzYzLWFkYjMtOWY1NGZjNWQ1YjdmIn0=", + "Timeout": 300, + "Input": {} + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 5, + "Id": "eccbc87e4b5ce2fe", + "Name": "initial-wait", + "EventTimestamp": "2025-12-12T00:05:31.139Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-12T00:05:32.139Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 6, + "EventTimestamp": "2025-12-12T00:05:31.141Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:05:31.127Z", + "EndTimestamp": "2025-12-12T00:05:31.141Z", + "Error": {}, + "RequestId": "1a48e171-2080-4f28-849a-9b13a6b268f3" + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 7, + "Id": "c81e728d9d4c2f63", + "Name": "process-user", + "EventTimestamp": "2025-12-12T00:05:31.238Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"processed\":true,\"timestamp\":1765497931237}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 8, + "EventTimestamp": "2025-12-12T00:05:31.241Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:05:31.239Z", + "EndTimestamp": "2025-12-12T00:05:31.241Z", + "Error": {}, + "RequestId": "a39e57be-733f-4623-bd5c-7e9705fb8505" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 9, + "Id": "eccbc87e4b5ce2fe", + "Name": "initial-wait", + "EventTimestamp": "2025-12-12T00:05:32.139Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 10, + "EventTimestamp": "2025-12-12T00:05:32.142Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:05:32.139Z", + "EndTimestamp": "2025-12-12T00:05:32.142Z", + "Error": {}, + "RequestId": "bbbdd7de-3c2a-4f9b-acf2-1bc245928289" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 11, + "Id": "420929c0-50c3-484b-9430-85d4f7b5d5a4", + "EventTimestamp": "2025-12-12T00:05:32.142Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"stepResult\":{\"userId\":123,\"name\":\"John Doe\"},\"callbackResult\":\"{\\\"processed\\\":true,\\\"timestamp\\\":1765497931237}\",\"completed\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/mixed-ops/create-callback-mixed-ops.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/mixed-ops/create-callback-mixed-ops.test.ts index f6e6d840..45f1a5a4 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/mixed-ops/create-callback-mixed-ops.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/mixed-ops/create-callback-mixed-ops.test.ts @@ -9,7 +9,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle callback operations mixed with other operation types", async () => { const callbackOperation = runner.getOperation("process-user"); @@ -18,6 +18,9 @@ createTests({ // Wait for callback to start (other operations complete synchronously) await callbackOperation.waitForData(WaitingOperationStatus.STARTED); + // Wait for invocation to complete + await new Promise((resolve) => setTimeout(resolve, 100)); + // Complete the callback const callbackResult = JSON.stringify({ processed: true, @@ -41,6 +44,8 @@ createTests({ expect(operationTypes).toContain(OperationType.WAIT); expect(operationTypes).toContain(OperationType.STEP); expect(operationTypes).toContain(OperationType.CALLBACK); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/serdes/create-callback-serdes.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/serdes/create-callback-serdes.history.json new file mode 100644 index 00000000..4af1a1c1 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/serdes/create-callback-serdes.history.json @@ -0,0 +1,72 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "7e2007fa-3f78-424d-817a-47fb55e32436", + "EventTimestamp": "2025-12-10T00:15:10.549Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "custom-serdes-callback", + "EventTimestamp": "2025-12-10T00:15:10.586Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImMxMjEzYWM0LWVmY2QtNDlkZi1hMjdlLWJjNWQ3MGUzYTg0OCIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiYmQ0NjQyZGYtMzJiYi00MzE3LThlMTUtZThjYWM0NWE4MTUxIn0=", + "Timeout": 300, + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "Name": "custom-serdes-callback", + "EventTimestamp": "2025-12-10T00:15:10.587Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"id\":42,\"message\":\"Hello World\",\"timestamp\":\"2025-01-01T00:00:00.000Z\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:10.646Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.549Z", + "EndTimestamp": "2025-12-10T00:15:10.646Z", + "Error": {}, + "RequestId": "9f7cbe60-1104-4ea4-b89a-af6ab03ba71a" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:10.668Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.667Z", + "EndTimestamp": "2025-12-10T00:15:10.668Z", + "Error": {}, + "RequestId": "f0958925-e623-4e52-ba25-14b296c58b68" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "7e2007fa-3f78-424d-817a-47fb55e32436", + "EventTimestamp": "2025-12-10T00:15:10.668Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"receivedData\":{\"id\":42,\"message\":\"Hello World\",\"timestamp\":\"2025-01-01T00:00:00.000Z\"},\"isDateObject\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/serdes/create-callback-serdes.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/serdes/create-callback-serdes.test.ts index e30fd6df..660493ab 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/serdes/create-callback-serdes.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/serdes/create-callback-serdes.test.ts @@ -30,7 +30,7 @@ const customSerdes = { createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle callback operations with custom serdes", async () => { const callbackOperation = runner.getOperation("custom-serdes-callback"); const executionPromise = runner.run(); @@ -58,6 +58,8 @@ createTests({ }), ), ); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-failure-undefined.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-failure-undefined.history.json new file mode 100644 index 00000000..c10f4802 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-failure-undefined.history.json @@ -0,0 +1,77 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "9dfc0ba2-68f6-4906-b673-e9fc7f730c35", + "EventTimestamp": "2025-12-10T00:15:09.336Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:09.362Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImYyNTVjNmY5LWRiNDQtNGI2Ni05M2IwLTg1YTE2NDZjNzlhOSIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiYjY2OTgyMzgtNTQ1OS00YThkLTkyNDgtZGQxOWNjNzY1M2Y3In0=", + "Input": {} + } + }, + { + "EventType": "CallbackFailed", + "SubType": "Callback", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:09.362Z", + "CallbackFailedDetails": { + "Error": { + "Payload": {} + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:09.423Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.336Z", + "EndTimestamp": "2025-12-10T00:15:09.423Z", + "Error": {}, + "RequestId": "1e5ef3b2-7095-41f4-8558-3eb54813d2d8" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:09.444Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.443Z", + "EndTimestamp": "2025-12-10T00:15:09.444Z", + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "Callback failed" + } + }, + "RequestId": "37732507-267a-411b-a1cd-654d05c66440" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 6, + "Id": "9dfc0ba2-68f6-4906-b673-e9fc7f730c35", + "EventTimestamp": "2025-12-10T00:15:09.445Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "Callback failed" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-failure.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-failure.history.json new file mode 100644 index 00000000..25d901a5 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-failure.history.json @@ -0,0 +1,79 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "36f807d8-a63f-42d8-a44d-ad73d36c78bc", + "EventTimestamp": "2025-12-10T00:15:08.867Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:08.910Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImQ0ODU1ZWRhLTlkOGUtNGQ3NC1hMmU5LTY1Yjg4MDNiMjc0OSIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiNzUzMjdjZGEtMDYxYy00YmM5LWEzOWEtNzljY2NiYWNlYWUxIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackFailed", + "SubType": "Callback", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:08.911Z", + "CallbackFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "ERROR" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:08.972Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.867Z", + "EndTimestamp": "2025-12-10T00:15:08.972Z", + "Error": {}, + "RequestId": "c547ab5d-6501-41ba-b720-bb7248c0af70" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:08.994Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.993Z", + "EndTimestamp": "2025-12-10T00:15:08.994Z", + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "ERROR" + } + }, + "RequestId": "e99100a2-77c5-4a49-a696-6788e90e27d4" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 6, + "Id": "36f807d8-a63f-42d8-a44d-ad73d36c78bc", + "EventTimestamp": "2025-12-10T00:15:08.994Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "ERROR" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-success-undefined.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-success-undefined.history.json new file mode 100644 index 00000000..f696c3c1 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-success-undefined.history.json @@ -0,0 +1,63 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "aeb42be9-bb93-4a04-b845-42dcca430046", + "EventTimestamp": "2025-12-10T00:15:09.097Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:09.141Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImNhNDZkMTFhLTk2ZGQtNDk3NC04ODkyLWE4Njc3ZDJkZTcwNiIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiYzBiYjVmZGUtMjYzNi00ZGM0LTlhZDUtODE3ZjkwZjFlY2Q3In0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:09.142Z", + "CallbackSucceededDetails": { + "Result": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:09.202Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.097Z", + "EndTimestamp": "2025-12-10T00:15:09.202Z", + "Error": {}, + "RequestId": "3e069eec-4204-4aea-afc4-518db3d6fa93" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:09.224Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.224Z", + "EndTimestamp": "2025-12-10T00:15:09.224Z", + "Error": {}, + "RequestId": "b27855c1-7ffd-4577-9185-60cee47f7607" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "aeb42be9-bb93-4a04-b845-42dcca430046", + "EventTimestamp": "2025-12-10T00:15:09.224Z", + "ExecutionSucceededDetails": {} + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-success.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-success.history.json new file mode 100644 index 00000000..474e1193 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback-success.history.json @@ -0,0 +1,69 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "e9657372-e8ef-4099-a5b5-6f3fb9e886da", + "EventTimestamp": "2025-12-10T00:15:08.642Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:08.678Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjM0ODU3NTUyLTNhMWMtNDgxYi05ZDNlLWUzZjM1ZjVhM2M3OCIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiMzlmOWU2ZTYtYWI0My00NjhhLTg5ZjQtMDBiZTNlOTQxZDMxIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:08.679Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "successful" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:08.739Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.642Z", + "EndTimestamp": "2025-12-10T00:15:08.739Z", + "Error": {}, + "RequestId": "76079409-2aa5-4ef4-b5fb-576798ed2d75" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:08.761Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.760Z", + "EndTimestamp": "2025-12-10T00:15:08.761Z", + "Error": {}, + "RequestId": "3205c33a-2785-455f-be9e-f9490e91a69d" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "e9657372-e8ef-4099-a5b5-6f3fb9e886da", + "EventTimestamp": "2025-12-10T00:15:08.761Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "\"successful\"" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback.test.ts index 82b26e44..68b86f16 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/simple/create-callback.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("function completes when callback succeeds - happy case", async () => { const res = "successful"; const executionPromise = runner.run(); @@ -21,6 +21,8 @@ createTests({ expect(callbackOp.getCallbackDetails()?.result).toStrictEqual(res); expect(execution.getResult()).toStrictEqual(res); + + assertEventSignatures(execution, "success"); }); it("function completes when callback fails - happy case", async () => { @@ -34,6 +36,8 @@ createTests({ expect(callbackOp.getCallbackDetails()?.error).toBeDefined(); expect(execution.getError()).toBeDefined(); + + assertEventSignatures(execution, "failure"); }); it("function completes when callback succeeds with undefined - edge case", async () => { @@ -48,6 +52,8 @@ createTests({ expect(callbackOp.getCallbackDetails()?.result).toBeUndefined(); expect(callbackOp.getCallbackDetails()?.error).toBeUndefined(); expect(execution.getResult()).toBeUndefined(); + + assertEventSignatures(execution, "success-undefined"); }); it("function completes when callback fails with undefined error message - edge case", async () => { @@ -67,6 +73,8 @@ createTests({ stackTrace: undefined, }); expect(execution.getError()).toBeDefined(); + + assertEventSignatures(execution, "failure-undefined"); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/timeout/create-callback-timeout.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/timeout/create-callback-timeout.history.json new file mode 100644 index 00000000..658150ad --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/timeout/create-callback-timeout.history.json @@ -0,0 +1,82 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "2a59b0ba-c037-4bf2-9659-a6e384d44356", + "EventTimestamp": "2025-12-10T00:12:21.428Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"timeoutType\":\"heartbeat\"}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "long-running-task", + "EventTimestamp": "2025-12-10T00:12:21.434Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjJkM2NjMjRkLTA1MWEtNDdhOC1iMzNmLWE5ZmE5NGQ5MDUwOSIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiZDM5NDgwMmQtZjVjZC00ZmNmLWEwYjgtMGE1Nzc3MDYyZTlhIn0=", + "HeartbeatTimeout": 1, + "Input": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 3, + "EventTimestamp": "2025-12-10T00:12:21.485Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:21.428Z", + "EndTimestamp": "2025-12-10T00:12:21.485Z", + "Error": {}, + "RequestId": "a083c5de-7d37-471a-a204-ce52a4ca54af" + } + }, + { + "EventType": "CallbackTimedOut", + "SubType": "Callback", + "EventId": 4, + "Id": "c4ca4238a0b92382", + "Name": "long-running-task", + "EventTimestamp": "2025-12-10T00:12:22.436Z", + "CallbackTimedOutDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Callback timed out on heartbeat" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:12:22.437Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:22.436Z", + "EndTimestamp": "2025-12-10T00:12:22.437Z", + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "Callback timed out on heartbeat" + } + }, + "RequestId": "292e244b-a3bd-416f-bc9a-55e5f5e78092" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 6, + "Id": "2a59b0ba-c037-4bf2-9659-a6e384d44356", + "EventTimestamp": "2025-12-10T00:12:22.437Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "Callback timed out on heartbeat" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/timeout/create-callback-timeout.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/timeout/create-callback-timeout.test.ts index a3d3b080..f26d572d 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/timeout/create-callback-timeout.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/create-callback/timeout/create-callback-timeout.test.ts @@ -3,7 +3,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should time out if there are no callback heartbeats", async () => { const result = await runner.run({ payload: { timeoutType: "heartbeat" }, @@ -15,6 +15,8 @@ createTests({ errorType: "CallbackError", stackTrace: undefined, }); + + assertEventSignatures(result); }); it("should time out if callback times out", async () => { @@ -28,6 +30,8 @@ createTests({ errorType: "CallbackError", stackTrace: undefined, }); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/callback/force-checkpointing-callback.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/callback/force-checkpointing-callback.history.json new file mode 100644 index 00000000..f06141da --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/callback/force-checkpointing-callback.history.json @@ -0,0 +1,209 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "1354deb8-60cc-41f3-a469-e8bb11156808", + "EventTimestamp": "2025-12-10T00:12:09.158Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:09.164Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:09.164Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "long-running-step", + "EventTimestamp": "2025-12-10T00:12:09.164Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:09.164Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "callback-1", + "EventTimestamp": "2025-12-10T00:12:09.164Z", + "ParentId": "98c6f2c2287f4c73", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImQ4NWMyMjM4LTU5NTYtNDdiYS05NTAyLWEwMDJhNWU5N2IzMCIsIm9wZXJhdGlvbklkIjoiNjE1MWY1YWIyODJkOTBlNCIsInRva2VuIjoiZmJiOTljNzMtYmYwOS00NzZkLWFlZDAtOTNkZDlmYTkyMmJjIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 7, + "Id": "6151f5ab282d90e4", + "Name": "callback-1", + "EventTimestamp": "2025-12-10T00:12:09.165Z", + "ParentId": "98c6f2c2287f4c73", + "CallbackSucceededDetails": { + "Result": { + "Payload": "callback-1-done" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 8, + "Id": "e61730e6717b1787", + "Name": "callback-2", + "EventTimestamp": "2025-12-10T00:12:10.168Z", + "ParentId": "98c6f2c2287f4c73", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImQ4NWMyMjM4LTU5NTYtNDdiYS05NTAyLWEwMDJhNWU5N2IzMCIsIm9wZXJhdGlvbklkIjoiZTYxNzMwZTY3MTdiMTc4NyIsInRva2VuIjoiY2Y4YzA5ZGQtM2YwYy00N2Y5LWI3OTAtYjU1MDQxN2NkNDdlIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 9, + "Id": "e61730e6717b1787", + "Name": "callback-2", + "EventTimestamp": "2025-12-10T00:12:10.168Z", + "ParentId": "98c6f2c2287f4c73", + "CallbackSucceededDetails": { + "Result": { + "Payload": "callback-2-done" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 10, + "Id": "453e406dcee4d181", + "Name": "callback-3", + "EventTimestamp": "2025-12-10T00:12:11.173Z", + "ParentId": "98c6f2c2287f4c73", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImQ4NWMyMjM4LTU5NTYtNDdiYS05NTAyLWEwMDJhNWU5N2IzMCIsIm9wZXJhdGlvbklkIjoiNDUzZTQwNmRjZWU0ZDE4MSIsInRva2VuIjoiM2Q4ZTZmYWYtOWQ2NS00MmRjLTk4YmUtNmFlNjhiOTUwZWZiIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 11, + "Id": "453e406dcee4d181", + "Name": "callback-3", + "EventTimestamp": "2025-12-10T00:12:11.173Z", + "ParentId": "98c6f2c2287f4c73", + "CallbackSucceededDetails": { + "Result": { + "Payload": "callback-3-done" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 12, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:12.178Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"callbacks-complete\"" + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 13, + "Id": "2f221a18eb863803", + "Name": "long-running-step", + "EventTimestamp": "2025-12-10T00:12:19.165Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"long-complete\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 14, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:19.168Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"long-complete\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 15, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:19.168Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"long-complete\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"result\":\"callbacks-complete\",\"index\":1,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"ALL_COMPLETED\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 16, + "EventTimestamp": "2025-12-10T00:12:19.170Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:09.158Z", + "EndTimestamp": "2025-12-10T00:12:19.170Z", + "Error": {}, + "RequestId": "c21bfd3a-4123-4b55-a333-470e9a59a1e3" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 17, + "Id": "1354deb8-60cc-41f3-a469-e8bb11156808", + "EventTimestamp": "2025-12-10T00:12:19.170Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "\"{\\\"all\\\":[{\\\"result\\\":\\\"long-complete\\\",\\\"index\\\":0,\\\"status\\\":\\\"SUCCEEDED\\\"},{\\\"result\\\":\\\"callbacks-complete\\\",\\\"index\\\":1,\\\"status\\\":\\\"SUCCEEDED\\\"}],\\\"completionReason\\\":\\\"ALL_COMPLETED\\\"}\"" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/callback/force-checkpointing-callback.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/callback/force-checkpointing-callback.test.ts index b8443232..348c6852 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/callback/force-checkpointing-callback.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/callback/force-checkpointing-callback.test.ts @@ -9,7 +9,7 @@ import { createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete with force checkpointing when one branch blocks termination with multiple callbacks", async () => { const startTime = Date.now(); @@ -56,6 +56,8 @@ createTests({ // Verify operations were tracked const operations = execution.getOperations(); expect(operations.length).toBeGreaterThan(0); + + assertEventSignatures(execution); }, 50000); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/invoke/force-checkpointing-invoke.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/invoke/force-checkpointing-invoke.history.json new file mode 100644 index 00000000..286884b2 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/invoke/force-checkpointing-invoke.history.json @@ -0,0 +1,212 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "b8ac939d-b10c-495b-9ed9-c5474d343820", + "EventTimestamp": "2025-12-10T00:12:07.577Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"functionNames\":[\"wait\",\"step-basic\",\"wait\"]}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:07.585Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:07.585Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "long-running-step", + "EventTimestamp": "2025-12-10T00:12:07.585Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:07.585Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "EventTimestamp": "2025-12-10T00:12:07.585Z", + "ParentId": "98c6f2c2287f4c73", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "ChainedInvokeSucceeded", + "SubType": "ChainedInvoke", + "EventId": 7, + "Id": "6151f5ab282d90e4", + "EventTimestamp": "2025-12-10T00:12:09.694Z", + "ParentId": "98c6f2c2287f4c73", + "ChainedInvokeSucceededDetails": { + "Result": { + "Payload": "\"Function Completed\"" + } + } + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 8, + "Id": "e61730e6717b1787", + "EventTimestamp": "2025-12-10T00:12:11.595Z", + "ParentId": "98c6f2c2287f4c73", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "ChainedInvokeSucceeded", + "SubType": "ChainedInvoke", + "EventId": 9, + "Id": "e61730e6717b1787", + "EventTimestamp": "2025-12-10T00:12:11.702Z", + "ParentId": "98c6f2c2287f4c73", + "ChainedInvokeSucceededDetails": { + "Result": { + "Payload": "\"step completed\"" + } + } + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 10, + "Id": "453e406dcee4d181", + "EventTimestamp": "2025-12-10T00:12:12.599Z", + "ParentId": "98c6f2c2287f4c73", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "ChainedInvokeSucceeded", + "SubType": "ChainedInvoke", + "EventId": 11, + "Id": "453e406dcee4d181", + "EventTimestamp": "2025-12-10T00:12:14.704Z", + "ParentId": "98c6f2c2287f4c73", + "ChainedInvokeSucceededDetails": { + "Result": { + "Payload": "\"Function Completed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 12, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:16.609Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"invokes-complete\"" + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 13, + "Id": "2f221a18eb863803", + "Name": "long-running-step", + "EventTimestamp": "2025-12-10T00:12:27.585Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"long-complete\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 14, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:27.587Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"long-complete\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 15, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:27.587Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"long-complete\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"result\":\"invokes-complete\",\"index\":1,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"ALL_COMPLETED\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 16, + "EventTimestamp": "2025-12-10T00:12:27.587Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:07.576Z", + "EndTimestamp": "2025-12-10T00:12:27.587Z", + "Error": {}, + "RequestId": "55467410-dbb1-4a06-ad2e-31a749af94bf" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 17, + "Id": "b8ac939d-b10c-495b-9ed9-c5474d343820", + "EventTimestamp": "2025-12-10T00:12:27.587Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "\"{\\\"all\\\":[{\\\"result\\\":\\\"long-complete\\\",\\\"index\\\":0,\\\"status\\\":\\\"SUCCEEDED\\\"},{\\\"result\\\":\\\"invokes-complete\\\",\\\"index\\\":1,\\\"status\\\":\\\"SUCCEEDED\\\"}],\\\"completionReason\\\":\\\"ALL_COMPLETED\\\"}\"" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/invoke/force-checkpointing-invoke.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/invoke/force-checkpointing-invoke.test.ts index 1cbdaa54..d404d747 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/invoke/force-checkpointing-invoke.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/invoke/force-checkpointing-invoke.test.ts @@ -9,7 +9,7 @@ import { handler as stepHandler } from "../../step/basic/step-basic"; createTests({ handler, - tests: (runner, { functionNameMap }) => { + tests: (runner, { functionNameMap, assertEventSignatures }) => { it("should complete with force checkpointing when one branch blocks termination with multiple invokes", async () => { // Register the invoked functions for local testing if (runner instanceof LocalDurableTestRunner) { @@ -58,6 +58,8 @@ createTests({ // Verify operations were tracked const operations = execution.getOperations(); expect(operations.length).toBeGreaterThan(0); + + assertEventSignatures(execution); }, 60000); // 60 second timeout }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/step-retry/force-checkpointing.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/step-retry/force-checkpointing.test.ts index f3956a68..8ea8ce27 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/step-retry/force-checkpointing.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/force-checkpointing/step-retry/force-checkpointing.test.ts @@ -4,7 +4,7 @@ import { ExecutionStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete with force checkpointing when one branch blocks termination", async () => { const startTime = Date.now(); @@ -33,6 +33,8 @@ createTests({ // Verify operations were tracked const operations = execution.getOperations(); expect(operations.length).toBeGreaterThan(0); + + assertEventSignatures(execution); }, 20000); // 20 second timeout }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-basic-wait.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-basic-wait.history.json new file mode 100644 index 00000000..dcc14bd6 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-basic-wait.history.json @@ -0,0 +1,72 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "c2ee5a66-7751-40e2-8c7b-8eb271518e37", + "EventTimestamp": "2025-12-10T00:12:22.591Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"functionName\":\"wait-named\"}" + } + } + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:22.594Z", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 3, + "EventTimestamp": "2025-12-10T00:12:22.646Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:22.591Z", + "EndTimestamp": "2025-12-10T00:12:22.646Z", + "Error": {}, + "RequestId": "451009d0-39ae-4b25-8ce7-8d4254ae153c" + } + }, + { + "EventType": "ChainedInvokeSucceeded", + "SubType": "ChainedInvoke", + "EventId": 4, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:24.701Z", + "ChainedInvokeSucceededDetails": { + "Result": { + "Payload": "\"wait finished\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:12:24.703Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:24.702Z", + "EndTimestamp": "2025-12-10T00:12:24.703Z", + "Error": {}, + "RequestId": "33341976-7210-4783-b505-9b4c61c6c274" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "c2ee5a66-7751-40e2-8c7b-8eb271518e37", + "EventTimestamp": "2025-12-10T00:12:24.703Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "\"wait finished\"" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-child-failure.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-child-failure.history.json new file mode 100644 index 00000000..9e31cbca --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-child-failure.history.json @@ -0,0 +1,83 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "7e80d670-4810-4737-8ad6-fc9c6b270f6d", + "EventTimestamp": "2025-12-10T00:12:25.024Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"functionName\":\"handler-error\"}" + } + } + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:25.029Z", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 3, + "EventTimestamp": "2025-12-10T00:12:25.080Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:25.024Z", + "EndTimestamp": "2025-12-10T00:12:25.080Z", + "Error": {}, + "RequestId": "a902cbf1-ac57-48f7-ab93-3ebcb6bf18da" + } + }, + { + "EventType": "ChainedInvokeFailed", + "SubType": "ChainedInvoke", + "EventId": 4, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:25.136Z", + "ChainedInvokeFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Intentional handler failure", + "ErrorType": "Error" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:12:25.139Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:25.138Z", + "EndTimestamp": "2025-12-10T00:12:25.139Z", + "Error": { + "Payload": { + "ErrorType": "InvokeError", + "ErrorMessage": "Intentional handler failure" + } + }, + "RequestId": "108e47a9-d884-4628-a1ec-fc170acfec7f" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 6, + "Id": "7e80d670-4810-4737-8ad6-fc9c6b270f6d", + "EventTimestamp": "2025-12-10T00:12:25.139Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "InvokeError", + "ErrorMessage": "Intentional handler failure" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-non-durable-failure.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-non-durable-failure.history.json new file mode 100644 index 00000000..2ba17f3e --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-non-durable-failure.history.json @@ -0,0 +1,94 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "35c882e2-c63d-4544-8cf8-ae18e1e868b9", + "EventTimestamp": "2025-12-10T00:15:10.766Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"functionName\":\"non-durable\",\"payload\":{\"failure\":true}}" + } + } + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:10.814Z", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "ChainedInvokeFailed", + "SubType": "ChainedInvoke", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:10.839Z", + "ChainedInvokeFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "This is a failure", + "ErrorType": "Error", + "StackTrace": [ + "Error: This is a failure", + " at handler (/Users/adting/workplace/lambda-durable-functions-sdk-js/packages/aws-durable-execution-sdk-js-examples/src/examples/non-durable/non-durable.ts:11:11)", + " at result (/Users/adting/workplace/lambda-durable-functions-sdk-js/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/operations/function-storage.ts:149:24)", + " at new Promise ()", + " at FunctionStorage.runHandler (/Users/adting/workplace/lambda-durable-functions-sdk-js/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/operations/function-storage.ts:148:28)", + " at TestExecutionOrchestrator.handleInvokeUpdate (/Users/adting/workplace/lambda-durable-functions-sdk-js/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/test-execution-orchestrator.ts:297:58)", + " at TestExecutionOrchestrator.processOperation (/Users/adting/workplace/lambda-durable-functions-sdk-js/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/test-execution-orchestrator.ts:272:14)", + " at TestExecutionOrchestrator.processOperations (/Users/adting/workplace/lambda-durable-functions-sdk-js/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/test-execution-orchestrator.ts:238:12)", + " at TestExecutionOrchestrator.pollForCheckpointData (/Users/adting/workplace/lambda-durable-functions-sdk-js/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/test-execution-orchestrator.ts:203:14)" + ] + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:10.880Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.766Z", + "EndTimestamp": "2025-12-10T00:15:10.880Z", + "Error": {}, + "RequestId": "fe13dfea-f8f4-424e-99ba-ad360f8afe42" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:10.902Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.901Z", + "EndTimestamp": "2025-12-10T00:15:10.902Z", + "Error": { + "Payload": { + "ErrorType": "InvokeError", + "ErrorMessage": "This is a failure" + } + }, + "RequestId": "bc497243-73e1-47d2-a01a-7c3ef8c7b0b1" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 6, + "Id": "35c882e2-c63d-4544-8cf8-ae18e1e868b9", + "EventTimestamp": "2025-12-10T00:15:10.902Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "InvokeError", + "ErrorMessage": "This is a failure" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-non-durable-success.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-non-durable-success.history.json new file mode 100644 index 00000000..6360c8c4 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-non-durable-success.history.json @@ -0,0 +1,72 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "5c002679-931c-4e9e-ac7a-62dbdf5a555d", + "EventTimestamp": "2025-12-10T00:12:25.242Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"functionName\":\"non-durable\"}" + } + } + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:25.245Z", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 3, + "EventTimestamp": "2025-12-10T00:12:25.297Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:25.242Z", + "EndTimestamp": "2025-12-10T00:12:25.297Z", + "Error": {}, + "RequestId": "24a3700d-f1b9-402d-9efd-a2b01025069f" + } + }, + { + "EventType": "ChainedInvokeSucceeded", + "SubType": "ChainedInvoke", + "EventId": 4, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:26.247Z", + "ChainedInvokeSucceededDetails": { + "Result": { + "Payload": "{\"status\":200,\"body\":\"{\\\"message\\\":\\\"Hello from Lambda!\\\"}\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:12:26.251Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:26.249Z", + "EndTimestamp": "2025-12-10T00:12:26.251Z", + "Error": {}, + "RequestId": "02c671e7-0994-40d2-adbe-4056113fd00d" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "5c002679-931c-4e9e-ac7a-62dbdf5a555d", + "EventTimestamp": "2025-12-10T00:12:26.251Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"status\":200,\"body\":\"{\\\"message\\\":\\\"Hello from Lambda!\\\"}\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-step-payload.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-step-payload.history.json new file mode 100644 index 00000000..0e312f50 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple-step-payload.history.json @@ -0,0 +1,72 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "69ff2915-abb7-4ea8-9359-d32b14ac164a", + "EventTimestamp": "2025-12-10T00:12:24.808Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"functionName\":\"step-named\",\"payload\":{\"data\":\"data from parent\"}}" + } + } + }, + { + "EventType": "ChainedInvokeStarted", + "SubType": "ChainedInvoke", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:24.811Z", + "ChainedInvokeStartedDetails": { + "FunctionName": "", + "Input": { + "Payload": "" + }, + "DurableExecutionArn": "" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 3, + "EventTimestamp": "2025-12-10T00:12:24.862Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:24.808Z", + "EndTimestamp": "2025-12-10T00:12:24.862Z", + "Error": {}, + "RequestId": "f0d4d2b8-a7bb-4d98-bae0-a0d17115b146" + } + }, + { + "EventType": "ChainedInvokeSucceeded", + "SubType": "ChainedInvoke", + "EventId": 4, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:24.915Z", + "ChainedInvokeSucceededDetails": { + "Result": { + "Payload": "\"processed: data from parent\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:12:24.917Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:24.917Z", + "EndTimestamp": "2025-12-10T00:12:24.917Z", + "Error": {}, + "RequestId": "58de6169-edd8-4b1e-abe2-6f4e79f00614" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "69ff2915-abb7-4ea8-9359-d32b14ac164a", + "EventTimestamp": "2025-12-10T00:12:24.918Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "\"processed: data from parent\"" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple.test.ts index bcae854b..983c6ac7 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/invoke/simple/invoke-simple.test.ts @@ -8,7 +8,7 @@ import { handler as namedStepHandler } from "../../step/named/step-named"; createTests({ handler, - tests: function (runner, { functionNameMap }) { + tests: function (runner, { functionNameMap, assertEventSignatures }) { it("should run invoke with basic wait state", async () => { if (runner instanceof LocalDurableTestRunner) { runner.registerDurableFunction( @@ -23,6 +23,8 @@ createTests({ }, }); expect(result.getResult()).toBe("wait finished"); + + assertEventSignatures(result, "basic-wait"); }); it("should run invoke with step and payload", async () => { @@ -42,6 +44,8 @@ createTests({ }, }); expect(result.getResult()).toEqual("processed: data from parent"); + + assertEventSignatures(result, "step-payload"); }); it("should run invoke with child function failure", async () => { @@ -61,6 +65,8 @@ createTests({ errorMessage: "Intentional handler failure", errorType: "InvokeError", }); + + assertEventSignatures(result, "child-failure"); }); it("should run invoke with non-durable function success", async () => { @@ -82,6 +88,8 @@ createTests({ message: "Hello from Lambda!", }), }); + + assertEventSignatures(result, "non-durable-success"); }); it("should run invoke with non-durable function failure", async () => { @@ -104,6 +112,8 @@ createTests({ errorMessage: "This is a failure", errorType: "InvokeError", }); + + assertEventSignatures(result, "non-durable-failure"); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/logger-test/after-callback/logger-after-callback.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/logger-test/after-callback/logger-after-callback.history.json new file mode 100644 index 00000000..08feefef --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/logger-test/after-callback/logger-after-callback.history.json @@ -0,0 +1,69 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "f2fd8f7e-f233-4f2d-991a-0590a5f1fcc3", + "EventTimestamp": "2025-12-10T00:15:08.650Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"logFilePath\":\"/var/folders/t8/39f5f5gj7kx35kt8s5bhqj6m0000gr/T/logger-test-9fad77ce-f12b-40c3-b098-46f751b54931.log\",\"modeAware\":true}" + } + } + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:08.675Z", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImU3ZTE3NGEwLWU5NjUtNGJmNC05ODMxLTk0YjE1Nzc0MTA1MSIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiYWUwYWFiZDctMjQwOS00MmMxLWJjYzctYzYyMDgxMThiMTNkIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:08.676Z", + "CallbackSucceededDetails": { + "Result": { + "Payload": "test-result" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:08.735Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.650Z", + "EndTimestamp": "2025-12-10T00:15:08.735Z", + "Error": {}, + "RequestId": "95ffa90f-3a62-4d70-b1be-d1404f0c386a" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:15:08.757Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.756Z", + "EndTimestamp": "2025-12-10T00:15:08.757Z", + "Error": {}, + "RequestId": "81aed61d-f37b-43be-bd06-696fc313accf" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 6, + "Id": "f2fd8f7e-f233-4f2d-991a-0590a5f1fcc3", + "EventTimestamp": "2025-12-10T00:15:08.757Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"message\":\"Success\",\"callbackId\":\"eyJleGVjdXRpb25JZCI6ImU3ZTE3NGEwLWU5NjUtNGJmNC05ODMxLTk0YjE1Nzc0MTA1MSIsIm9wZXJhdGlvbklkIjoiYzRjYTQyMzhhMGI5MjM4MiIsInRva2VuIjoiYWUwYWFiZDctMjQwOS00MmMxLWJjYzctYzYyMDgxMThiMTNkIn0=\",\"result\":\"test-result\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/logger-test/after-callback/logger-after-callback.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/logger-test/after-callback/logger-after-callback.test.ts index a333a4ef..c3f8e9b2 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/logger-test/after-callback/logger-after-callback.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/logger-test/after-callback/logger-after-callback.test.ts @@ -12,7 +12,7 @@ import { randomUUID } from "crypto"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner, isCloud) => { + tests: (runner, { isCloud, assertEventSignatures }) => { if (!isCloud) { it("should log correctly with modeAware=true", async () => { const logFilePath = path.join( @@ -58,6 +58,8 @@ createTests({ // - "After createCallback" appears once (after callback resolves, in execution mode) expect(beforeCallbackLogs.length).toBe(1); expect(afterCallbackLogs.length).toBe(1); + + assertEventSignatures(execution); } finally { if (fs.existsSync(logFilePath)) { fs.unlinkSync(logFilePath); @@ -107,24 +109,28 @@ createTests({ // - "After createCallback" appears once (after callback resolves) expect(beforeCallbackLogs.length).toBe(2); expect(afterCallbackLogs.length).toBe(1); + + assertEventSignatures(execution); } finally { if (fs.existsSync(logFilePath)) { fs.unlinkSync(logFilePath); } } }); - } + } else { + it("should execute successfully", async () => { + const executionPromise = runner.run(); - it("should execute successfully", async () => { - const executionPromise = runner.run(); + const callbackOp = runner.getOperationByIndex(0); + await callbackOp.waitForData(WaitingOperationStatus.STARTED); + await callbackOp.sendCallbackSuccess("test-result"); - const callbackOp = runner.getOperationByIndex(0); - await callbackOp.waitForData(WaitingOperationStatus.STARTED); - await callbackOp.sendCallbackSuccess("test-result"); + const execution = await executionPromise; + const result = execution.getResult() as any; + expect(result.message).toBe("Success"); - const execution = await executionPromise; - const result = execution.getResult() as any; - expect(result.message).toBe("Success"); - }); + assertEventSignatures(execution); + }); + } }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-count/map-failure-threshold-exceeded-count.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-count/map-failure-threshold-exceeded-count.history.json new file mode 100644 index 00000000..7dcddb95 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-count/map-failure-threshold-exceeded-count.history.json @@ -0,0 +1,473 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "dfeefa8f-8522-49d4-b8a0-0adb383962d6", + "EventTimestamp": "2025-12-10T00:14:18.046Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Map", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-items", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 13, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:14:18.080Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 2, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 14, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:14:18.086Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 1, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 15, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:14:18.086Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 2, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-10T00:14:18.086Z", + "ParentId": "3a170a9fe4f47efa", + "StepSucceededDetails": { + "Result": { + "Payload": "8" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-10T00:14:18.086Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "10" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 18, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-10T00:14:18.090Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "8" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 19, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-10T00:14:18.090Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "10" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 20, + "EventTimestamp": "2025-12-10T00:14:18.139Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:14:18.046Z", + "EndTimestamp": "2025-12-10T00:14:18.139Z", + "Error": {}, + "RequestId": "d63bf0b3-dc58-4aa8-8a9e-3ce24cb48d86" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 21, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:14:19.089Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 22, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:14:19.089Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 23, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-10T00:14:19.091Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Item 2 failed" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 24, + "EventTimestamp": "2025-12-10T00:14:19.140Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:14:19.087Z", + "EndTimestamp": "2025-12-10T00:14:19.140Z", + "Error": {}, + "RequestId": "51db7b2b-74c1-4c06-9717-e23a40b8e997" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 25, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:14:20.085Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 26, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:14:20.085Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 27, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-10T00:14:20.089Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Item 1 failed" + } + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 28, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:14:20.092Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 29, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:14:20.092Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 30, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-10T00:14:20.096Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Item 3 failed" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Map", + "EventId": 31, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-items", + "EventTimestamp": "2025-12-10T00:14:20.096Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":0,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":1,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":2,\"status\":\"FAILED\"},{\"result\":8,\"index\":3,\"status\":\"SUCCEEDED\"},{\"result\":10,\"index\":4,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 32, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:14:20.096Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:14:21.096Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 33, + "EventTimestamp": "2025-12-10T00:14:20.148Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:14:20.082Z", + "EndTimestamp": "2025-12-10T00:14:20.148Z", + "Error": {}, + "RequestId": "c1852b3b-388c-4904-a611-ad6dc0c422f0" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 34, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:14:21.098Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 35, + "EventTimestamp": "2025-12-10T00:14:21.101Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:14:21.098Z", + "EndTimestamp": "2025-12-10T00:14:21.101Z", + "Error": {}, + "RequestId": "8960e15c-7773-408c-9e0e-5efdfb89c535" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 36, + "Id": "dfeefa8f-8522-49d4-b8a0-0adb383962d6", + "EventTimestamp": "2025-12-10T00:14:21.101Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\",\"successCount\":2,\"failureCount\":3,\"totalCount\":5}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-count/map-failure-threshold-exceeded-count.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-count/map-failure-threshold-exceeded-count.test.ts index e52be164..0697a4fe 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-count/map-failure-threshold-exceeded-count.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-count/map-failure-threshold-exceeded-count.test.ts @@ -4,7 +4,7 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should return FAILURE_TOLERANCE_EXCEEDED when failure count exceeds threshold", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -24,6 +24,8 @@ createTests({ ].forEach(({ name, status }) => { expect(runner.getOperation(name)?.getStatus()).toBe(status); }); + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-percentage/map-failure-threshold-exceeded-percentage.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-percentage/map-failure-threshold-exceeded-percentage.history.json new file mode 100644 index 00000000..21d433af --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-percentage/map-failure-threshold-exceeded-percentage.history.json @@ -0,0 +1,484 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "466e5072-8e3f-4b60-9c5d-0e345fa38e2f", + "EventTimestamp": "2025-12-12T00:34:22.994Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Map", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-items", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 13, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-12T00:34:23.001Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 1, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 14, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-12T00:34:23.003Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 5, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 15, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-12T00:34:23.003Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 2, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-12T00:34:23.003Z", + "ParentId": "3a170a9fe4f47efa", + "StepSucceededDetails": { + "Result": { + "Payload": "8" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-12T00:34:23.003Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "10" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 18, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-12T00:34:23.006Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "8" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 19, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-12T00:34:23.006Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "10" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 20, + "EventTimestamp": "2025-12-12T00:34:23.007Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:22.994Z", + "EndTimestamp": "2025-12-12T00:34:23.007Z", + "Error": {}, + "RequestId": "13a80d9b-8923-464c-9463-d7d7328681c3" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 21, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-12T00:34:24.007Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 22, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-12T00:34:24.007Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 23, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-12T00:34:24.011Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Item 1 failed" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 24, + "EventTimestamp": "2025-12-12T00:34:24.012Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:24.004Z", + "EndTimestamp": "2025-12-12T00:34:24.012Z", + "Error": {}, + "RequestId": "5a9d24c8-2790-4961-b172-24ccf9f90587" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 25, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-12T00:34:25.012Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 26, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-12T00:34:25.012Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 27, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-12T00:34:25.015Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Item 3 failed" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 28, + "EventTimestamp": "2025-12-12T00:34:25.016Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:25.006Z", + "EndTimestamp": "2025-12-12T00:34:25.016Z", + "Error": {}, + "RequestId": "52caa01c-416f-4f4e-89c4-029a9ecffd70" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 29, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-12T00:34:28.006Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 30, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-12T00:34:28.006Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Item 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 31, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-12T00:34:28.008Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Item 2 failed" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Map", + "EventId": 32, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-items", + "EventTimestamp": "2025-12-12T00:34:28.008Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":0,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":1,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":2,\"status\":\"FAILED\"},{\"result\":8,\"index\":3,\"status\":\"SUCCEEDED\"},{\"result\":10,\"index\":4,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 33, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-12T00:34:28.008Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-12T00:34:29.008Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 34, + "EventTimestamp": "2025-12-12T00:34:28.010Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:28.004Z", + "EndTimestamp": "2025-12-12T00:34:28.010Z", + "Error": {}, + "RequestId": "e3fbfbad-bc86-4c3b-951d-2ba6fe7b62ba" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 35, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-12T00:34:29.009Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 36, + "EventTimestamp": "2025-12-12T00:34:29.012Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:29.009Z", + "EndTimestamp": "2025-12-12T00:34:29.012Z", + "Error": {}, + "RequestId": "840af57f-8222-4df3-8db7-5c7ffd5858e1" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 37, + "Id": "466e5072-8e3f-4b60-9c5d-0e345fa38e2f", + "EventTimestamp": "2025-12-12T00:34:29.012Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\",\"successCount\":2,\"failureCount\":3,\"totalCount\":5}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-percentage/map-failure-threshold-exceeded-percentage.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-percentage/map-failure-threshold-exceeded-percentage.test.ts index dfa0b183..069f10c4 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-percentage/map-failure-threshold-exceeded-percentage.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/failure-threshold-exceeded-percentage/map-failure-threshold-exceeded-percentage.test.ts @@ -4,7 +4,7 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should return FAILURE_TOLERANCE_EXCEEDED when failure percentage exceeds threshold", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -24,6 +24,10 @@ createTests({ ].forEach(({ name, status }) => { expect(runner.getOperation(name)?.getStatus()).toBe(status); }); + + assertEventSignatures(execution, undefined, { + invocationCompletedDifference: 1, + }); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/min-successful/map-min-successful.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/min-successful/map-min-successful.history.json new file mode 100644 index 00000000..ff8e7a52 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/min-successful/map-min-successful.history.json @@ -0,0 +1,334 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "023ef399-731b-47ff-88cb-046d628ad1a4", + "EventTimestamp": "2025-12-11T23:34:27.714Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Map", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "min-successful-items", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-11T23:34:28.459Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 13, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-11T23:34:29.176Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 1 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 14, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-11T23:34:29.176Z", + "ParentId": "98c6f2c2287f4c73", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 2 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 15, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-11T23:34:29.176Z", + "ParentId": "13cee27a2bd93915", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 3 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-11T23:34:29.176Z", + "ParentId": "3a170a9fe4f47efa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 4 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-11T23:34:29.176Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 5 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 18, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-11T23:34:29.894Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 1 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 19, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-11T23:34:29.894Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 2 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 20, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-11T23:34:29.894Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 3 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 21, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-11T23:34:29.894Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 4 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 22, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-11T23:34:29.895Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 5 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Map", + "EventId": 23, + "Id": "c4ca4238a0b92382", + "Name": "min-successful-items", + "EventTimestamp": "2025-12-11T23:34:29.895Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"Item 1 processed\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"result\":\"Item 2 processed\",\"index\":1,\"status\":\"SUCCEEDED\"},{\"index\":2,\"status\":\"STARTED\"},{\"index\":3,\"status\":\"STARTED\"},{\"index\":4,\"status\":\"STARTED\"}],\"completionReason\":\"MIN_SUCCESSFUL_REACHED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 24, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-11T23:34:29.899Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-11T23:34:30.899Z" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 25, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-11T23:34:29.902Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 26, + "EventTimestamp": "2025-12-11T23:34:29.902Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T23:34:27.714Z", + "EndTimestamp": "2025-12-11T23:34:29.902Z", + "Error": {}, + "RequestId": "a81f172b-84ed-4cae-8a29-6d0fab025beb" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 27, + "EventTimestamp": "2025-12-11T23:34:29.925Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T23:34:29.921Z", + "EndTimestamp": "2025-12-11T23:34:29.925Z", + "Error": {}, + "RequestId": "14a648a0-a4d7-482d-aeec-52cca0c842f5" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 28, + "Id": "023ef399-731b-47ff-88cb-046d628ad1a4", + "EventTimestamp": "2025-12-11T23:34:29.925Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"successCount\":2,\"totalCount\":5,\"completionReason\":\"MIN_SUCCESSFUL_REACHED\",\"results\":[\"Item 1 processed\",\"Item 2 processed\"]}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/min-successful/map-min-successful.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/min-successful/map-min-successful.test.ts index 8eb7c408..cfd5ab96 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/min-successful/map-min-successful.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/min-successful/map-min-successful.test.ts @@ -4,7 +4,10 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + localRunnerConfig: { + checkpointDelay: 700, + }, + tests: (runner, { assertEventSignatures }) => { it("should complete early when minSuccessful is reached", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -31,7 +34,7 @@ createTests({ expect(item1?.getStatus()).toBe(OperationStatus.SUCCEEDED); // TODO: Re-enable these assertions when we find the root cause of the cloud timing issue - // where remaining items show SUCCEEDED instead of STARTED + // where remaining items show SUCCEEDED instead of STARTED https://github.com/aws/aws-durable-execution-sdk-js/issues/367 // Remaining items should be in STARTED state (not completed) // expect(item2?.getStatus()).toBe(OperationStatus.STARTED); // expect(item3?.getStatus()).toBe(OperationStatus.STARTED); @@ -39,6 +42,8 @@ createTests({ // Verify the results array matches expect(result.results).toEqual(["Item 1 processed", "Item 2 processed"]); + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-count/map-tolerated-failure-count.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-count/map-tolerated-failure-count.history.json new file mode 100644 index 00000000..f3fd9d1c --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-count/map-tolerated-failure-count.history.json @@ -0,0 +1,350 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "68762d3e-bf8a-4214-8592-6ecb25c032b9", + "EventTimestamp": "2025-12-10T00:12:09.149Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Map", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-count-items", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 13, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Processing failed for item 2", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 14, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "3a170a9fe4f47efa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Processing failed for item 4", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 15, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 1 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "13cee27a2bd93915", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 3 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-10T00:12:09.154Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 5 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 18, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-10T00:12:09.157Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Processing failed for item 2" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 19, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-10T00:12:09.157Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Processing failed for item 4" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 20, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-10T00:12:09.157Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 1 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 21, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-10T00:12:09.157Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 3 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 22, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-10T00:12:09.157Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 5 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Map", + "EventId": 23, + "Id": "c4ca4238a0b92382", + "Name": "failure-count-items", + "EventTimestamp": "2025-12-10T00:12:09.157Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"Item 1 processed\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":1,\"status\":\"FAILED\"},{\"result\":\"Item 3 processed\",\"index\":2,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":3,\"status\":\"FAILED\"},{\"result\":\"Item 5 processed\",\"index\":4,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"ALL_COMPLETED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 24, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:09.157Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:12:10.157Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 25, + "EventTimestamp": "2025-12-10T00:12:09.210Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:09.148Z", + "EndTimestamp": "2025-12-10T00:12:09.210Z", + "Error": {}, + "RequestId": "426c5dd9-da62-43ce-bd84-0f16d855ee95" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 26, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:10.158Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 27, + "EventTimestamp": "2025-12-10T00:12:10.160Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:10.159Z", + "EndTimestamp": "2025-12-10T00:12:10.160Z", + "Error": {}, + "RequestId": "bdfb5652-5562-41bd-b9bc-690d2e175007" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 28, + "Id": "68762d3e-bf8a-4214-8592-6ecb25c032b9", + "EventTimestamp": "2025-12-10T00:12:10.160Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"successCount\":3,\"failureCount\":2,\"totalCount\":5,\"completionReason\":\"ALL_COMPLETED\",\"hasFailure\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-count/map-tolerated-failure-count.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-count/map-tolerated-failure-count.test.ts index 0c664983..1e9dccbe 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-count/map-tolerated-failure-count.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-count/map-tolerated-failure-count.test.ts @@ -4,7 +4,7 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete when failure tolerance is reached", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -26,6 +26,8 @@ createTests({ ].forEach(({ name, status }) => { expect(runner.getOperation(name)?.getStatus()).toBe(status); }); + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-percentage/map-tolerated-failure-percentage.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-percentage/map-tolerated-failure-percentage.history.json new file mode 100644 index 00000000..5c7bce0a --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-percentage/map-tolerated-failure-percentage.history.json @@ -0,0 +1,603 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "86d63f39-976e-40da-9a9c-1f4927c7f7b3", + "EventTimestamp": "2025-12-10T00:12:07.585Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Map", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-percentage-items", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 13, + "Id": "449daf85c71a9f8e", + "Name": "map-item-5", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 14, + "Id": "eb1e930ffcc9bd72", + "Name": "process-5", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "449daf85c71a9f8e", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 15, + "Id": "6813b5c7ce3f9204", + "Name": "map-item-6", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 16, + "Id": "da76a88f237d9e53", + "Name": "process-6", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "6813b5c7ce3f9204", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 17, + "Id": "d04b95489bc4e2bc", + "Name": "map-item-7", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 18, + "Id": "7bb95ef96d539344", + "Name": "process-7", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "d04b95489bc4e2bc", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 19, + "Id": "2f15587a6a4cc313", + "Name": "map-item-8", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 20, + "Id": "e02ec69c09b4932d", + "Name": "process-8", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "2f15587a6a4cc313", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "MapIteration", + "EventId": 21, + "Id": "dd56b78777e20754", + "Name": "map-item-9", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 22, + "Id": "d3457e8fe9c52dd1", + "Name": "process-9", + "EventTimestamp": "2025-12-10T00:12:07.594Z", + "ParentId": "dd56b78777e20754", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 23, + "Id": "b425e0c75591aa8f", + "Name": "process-2", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Processing failed for item 3", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 24, + "Id": "eb1e930ffcc9bd72", + "Name": "process-5", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "449daf85c71a9f8e", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Processing failed for item 6", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 25, + "Id": "e02ec69c09b4932d", + "Name": "process-8", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "2f15587a6a4cc313", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Processing failed for item 9", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 26, + "Id": "2f221a18eb863803", + "Name": "process-0", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 1 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 27, + "Id": "6151f5ab282d90e4", + "Name": "process-1", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "98c6f2c2287f4c73", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 2 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 28, + "Id": "a4e1cd317d54f087", + "Name": "process-3", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "3a170a9fe4f47efa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 4 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 29, + "Id": "0f42756e5788f9b0", + "Name": "process-4", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 5 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 30, + "Id": "da76a88f237d9e53", + "Name": "process-6", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "6813b5c7ce3f9204", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 7 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 31, + "Id": "7bb95ef96d539344", + "Name": "process-7", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "d04b95489bc4e2bc", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 8 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 32, + "Id": "d3457e8fe9c52dd1", + "Name": "process-9", + "EventTimestamp": "2025-12-10T00:12:07.595Z", + "ParentId": "dd56b78777e20754", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Item 10 processed\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 33, + "Id": "13cee27a2bd93915", + "Name": "map-item-2", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Processing failed for item 3" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 34, + "Id": "449daf85c71a9f8e", + "Name": "map-item-5", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Processing failed for item 6" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "MapIteration", + "EventId": 35, + "Id": "2f15587a6a4cc313", + "Name": "map-item-8", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Processing failed for item 9" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 36, + "Id": "ea66c06c1e1c05fa", + "Name": "map-item-0", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 1 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 37, + "Id": "98c6f2c2287f4c73", + "Name": "map-item-1", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 2 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 38, + "Id": "3a170a9fe4f47efa", + "Name": "map-item-3", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 4 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 39, + "Id": "12426c956d1bc501", + "Name": "map-item-4", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 5 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 40, + "Id": "6813b5c7ce3f9204", + "Name": "map-item-6", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 7 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 41, + "Id": "d04b95489bc4e2bc", + "Name": "map-item-7", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 8 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "MapIteration", + "EventId": 42, + "Id": "dd56b78777e20754", + "Name": "map-item-9", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Item 10 processed\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Map", + "EventId": 43, + "Id": "c4ca4238a0b92382", + "Name": "failure-percentage-items", + "EventTimestamp": "2025-12-10T00:12:07.600Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"Item 1 processed\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"result\":\"Item 2 processed\",\"index\":1,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":2,\"status\":\"FAILED\"},{\"result\":\"Item 4 processed\",\"index\":3,\"status\":\"SUCCEEDED\"},{\"result\":\"Item 5 processed\",\"index\":4,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":5,\"status\":\"FAILED\"},{\"result\":\"Item 7 processed\",\"index\":6,\"status\":\"SUCCEEDED\"},{\"result\":\"Item 8 processed\",\"index\":7,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":8,\"status\":\"FAILED\"},{\"result\":\"Item 10 processed\",\"index\":9,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"ALL_COMPLETED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 44, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:07.601Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:12:08.601Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 45, + "EventTimestamp": "2025-12-10T00:12:07.653Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:07.585Z", + "EndTimestamp": "2025-12-10T00:12:07.653Z", + "Error": {}, + "RequestId": "2b347dce-bb63-4c65-a1de-b4197fa02a96" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 46, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:08.601Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 47, + "EventTimestamp": "2025-12-10T00:12:08.604Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:08.602Z", + "EndTimestamp": "2025-12-10T00:12:08.604Z", + "Error": {}, + "RequestId": "321a6295-4ed9-4b0f-b587-c3f573e48f10" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 48, + "Id": "86d63f39-976e-40da-9a9c-1f4927c7f7b3", + "EventTimestamp": "2025-12-10T00:12:08.604Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"successCount\":7,\"failureCount\":3,\"totalCount\":10,\"failurePercentage\":30,\"completionReason\":\"ALL_COMPLETED\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-percentage/map-tolerated-failure-percentage.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-percentage/map-tolerated-failure-percentage.test.ts index 539778b8..53a0a0a9 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-percentage/map-tolerated-failure-percentage.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/map/tolerated-failure-percentage/map-tolerated-failure-percentage.test.ts @@ -4,7 +4,7 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete with acceptable failure percentage", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -27,6 +27,8 @@ createTests({ ].forEach(({ name, status }) => { expect(runner.getOperation(name)?.getStatus()).toBe(status); }); + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/basic/parallel-basic.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/basic/parallel-basic.test.ts index c4fc3e60..5c65cf0e 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/basic/parallel-basic.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/basic/parallel-basic.test.ts @@ -4,20 +4,15 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, tests: (runner, { assertEventSignatures }) => { - it("should run correct number of durable steps", async () => { - const execution = await runner.run(); - - expect(runner.getOperation("parallel").getChildOperations()).toHaveLength( - 3, - ); - }); - it("should return correct result", async () => { const execution = await runner.run(); const result = execution.getResult(); expect(execution.getResult()).toBeDefined(); + expect(runner.getOperation("parallel").getChildOperations()).toHaveLength( + 3, + ); assertEventSignatures(execution); }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-count/parallel-failure-threshold-exceeded-count.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-count/parallel-failure-threshold-exceeded-count.history.json new file mode 100644 index 00000000..d14d70d9 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-count/parallel-failure-threshold-exceeded-count.history.json @@ -0,0 +1,484 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "4fd876c5-8911-4cd6-9c63-0dfb81d69a06", + "EventTimestamp": "2025-12-12T00:34:22.982Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-tasks", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "task-4", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "task-5", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 13, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:22.988Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 1, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 14, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:22.990Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 4, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 15, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:22.990Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 3, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "a4e1cd317d54f087", + "Name": "task-4", + "EventTimestamp": "2025-12-12T00:34:22.990Z", + "ParentId": "3a170a9fe4f47efa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Task 4 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "task-5", + "EventTimestamp": "2025-12-12T00:34:22.990Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Task 5 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 18, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-12T00:34:22.994Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Task 4 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 19, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-12T00:34:22.994Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Task 5 success\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 20, + "EventTimestamp": "2025-12-12T00:34:22.994Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:22.981Z", + "EndTimestamp": "2025-12-12T00:34:22.994Z", + "Error": {}, + "RequestId": "f59efb03-4778-4516-a85f-341ed3f9302c" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 21, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:23.995Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 22, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:23.995Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 23, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-12T00:34:23.997Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Task 1 failed" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 24, + "EventTimestamp": "2025-12-12T00:34:23.998Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:23.991Z", + "EndTimestamp": "2025-12-12T00:34:23.998Z", + "Error": {}, + "RequestId": "aa0ae911-0c67-473b-9329-8fb173e7d0e7" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 25, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:25.998Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 26, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:25.998Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 27, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-12T00:34:26.000Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Task 3 failed" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 28, + "EventTimestamp": "2025-12-12T00:34:26.000Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:25.994Z", + "EndTimestamp": "2025-12-12T00:34:26.000Z", + "Error": {}, + "RequestId": "5ce446a1-7dec-45eb-8618-615ad761c006" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 29, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:26.996Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 30, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:26.996Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 31, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-12T00:34:26.998Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Task 2 failed" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 32, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-tasks", + "EventTimestamp": "2025-12-12T00:34:26.998Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":0,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":1,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":2,\"status\":\"FAILED\"},{\"result\":\"Task 4 success\",\"index\":3,\"status\":\"SUCCEEDED\"},{\"result\":\"Task 5 success\",\"index\":4,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 33, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-12T00:34:26.998Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-12T00:34:27.998Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 34, + "EventTimestamp": "2025-12-12T00:34:27.000Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:26.993Z", + "EndTimestamp": "2025-12-12T00:34:27.000Z", + "Error": {}, + "RequestId": "9929a2af-9673-4a45-a136-0f2791d12ab9" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 35, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-12T00:34:27.999Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 36, + "EventTimestamp": "2025-12-12T00:34:28.001Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:28.000Z", + "EndTimestamp": "2025-12-12T00:34:28.001Z", + "Error": {}, + "RequestId": "e645175c-28ef-45bc-b56f-6210cbe7b511" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 37, + "Id": "4fd876c5-8911-4cd6-9c63-0dfb81d69a06", + "EventTimestamp": "2025-12-12T00:34:28.001Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\",\"successCount\":2,\"failureCount\":3,\"totalCount\":5}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-count/parallel-failure-threshold-exceeded-count.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-count/parallel-failure-threshold-exceeded-count.test.ts index e90a380f..07ffd5c1 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-count/parallel-failure-threshold-exceeded-count.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-count/parallel-failure-threshold-exceeded-count.test.ts @@ -3,7 +3,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should return FAILURE_TOLERANCE_EXCEEDED when failure count exceeds threshold", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -12,6 +12,10 @@ createTests({ expect(result.successCount).toBe(2); // Tasks 4 and 5 succeed expect(result.failureCount).toBe(3); // Tasks 1, 2, 3 fail (exceeds threshold of 2) expect(result.totalCount).toBe(5); + + assertEventSignatures(execution, undefined, { + invocationCompletedDifference: 1, + }); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-percentage/parallel-failure-threshold-exceeded-percentage.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-percentage/parallel-failure-threshold-exceeded-percentage.history.json new file mode 100644 index 00000000..9f3c18dd --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-percentage/parallel-failure-threshold-exceeded-percentage.history.json @@ -0,0 +1,473 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "6195d06b-1435-46f4-b5a0-fea943f76af9", + "EventTimestamp": "2025-12-12T00:34:22.961Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-tasks", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "task-4", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "task-5", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 13, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:22.969Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 1, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 14, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:22.971Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 1, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 15, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:22.971Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 2, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "a4e1cd317d54f087", + "Name": "task-4", + "EventTimestamp": "2025-12-12T00:34:22.971Z", + "ParentId": "3a170a9fe4f47efa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Task 4 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "task-5", + "EventTimestamp": "2025-12-12T00:34:22.971Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Task 5 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 18, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-12T00:34:22.974Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Task 4 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 19, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-12T00:34:22.974Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Task 5 success\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 20, + "EventTimestamp": "2025-12-12T00:34:22.975Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:22.960Z", + "EndTimestamp": "2025-12-12T00:34:22.975Z", + "Error": {}, + "RequestId": "356c3e0e-fdc9-4e0d-a720-129b013de4ff" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 21, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:23.977Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 22, + "Id": "2f221a18eb863803", + "Name": "task-1", + "EventTimestamp": "2025-12-12T00:34:23.977Z", + "ParentId": "ea66c06c1e1c05fa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 1 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 23, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:23.979Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 24, + "Id": "6151f5ab282d90e4", + "Name": "task-2", + "EventTimestamp": "2025-12-12T00:34:23.979Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 25, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-12T00:34:23.979Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Task 1 failed" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 26, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-12T00:34:23.982Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Task 2 failed" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 27, + "EventTimestamp": "2025-12-12T00:34:23.982Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:23.971Z", + "EndTimestamp": "2025-12-12T00:34:23.982Z", + "Error": {}, + "RequestId": "0645d44e-7feb-452e-9f09-8b3f18546e06" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 28, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:24.979Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 29, + "Id": "b425e0c75591aa8f", + "Name": "task-3", + "EventTimestamp": "2025-12-12T00:34:24.979Z", + "ParentId": "13cee27a2bd93915", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Task 3 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 30, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-12T00:34:24.983Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Task 3 failed" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 31, + "Id": "c4ca4238a0b92382", + "Name": "failure-threshold-tasks", + "EventTimestamp": "2025-12-12T00:34:24.983Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":0,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":1,\"status\":\"FAILED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":2,\"status\":\"FAILED\"},{\"result\":\"Task 4 success\",\"index\":3,\"status\":\"SUCCEEDED\"},{\"result\":\"Task 5 success\",\"index\":4,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 32, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-12T00:34:24.983Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-12T00:34:25.983Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 33, + "EventTimestamp": "2025-12-12T00:34:24.985Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:24.973Z", + "EndTimestamp": "2025-12-12T00:34:24.985Z", + "Error": {}, + "RequestId": "f4cf5407-ad20-4d1b-bc12-abeecbd4d5d3" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 34, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-12T00:34:25.985Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 35, + "EventTimestamp": "2025-12-12T00:34:25.989Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:34:25.986Z", + "EndTimestamp": "2025-12-12T00:34:25.989Z", + "Error": {}, + "RequestId": "c785cb90-b5a3-4a39-8c5c-d32e3d05621e" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 36, + "Id": "6195d06b-1435-46f4-b5a0-fea943f76af9", + "EventTimestamp": "2025-12-12T00:34:25.989Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"completionReason\":\"FAILURE_TOLERANCE_EXCEEDED\",\"successCount\":2,\"failureCount\":3,\"totalCount\":5}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-percentage/parallel-failure-threshold-exceeded-percentage.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-percentage/parallel-failure-threshold-exceeded-percentage.test.ts index 4bf35aa1..ec45c8b3 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-percentage/parallel-failure-threshold-exceeded-percentage.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/failure-threshold-exceeded-percentage/parallel-failure-threshold-exceeded-percentage.test.ts @@ -3,7 +3,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should return FAILURE_TOLERANCE_EXCEEDED when failure percentage exceeds threshold", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -12,6 +12,10 @@ createTests({ expect(result.successCount).toBe(2); // Tasks 4 and 5 succeed expect(result.failureCount).toBe(3); // Tasks 1, 2, 3 fail (60% > 50% threshold) expect(result.totalCount).toBe(5); + + assertEventSignatures(execution, undefined, { + invocationCompletedDifference: 1, + }); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful-with-callback/parallel-min-successful-callback.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful-with-callback/parallel-min-successful-callback.history.json new file mode 100644 index 00000000..da0f7162 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful-with-callback/parallel-min-successful-callback.history.json @@ -0,0 +1,165 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "51465649-ee49-44fe-bd23-8f493687450a", + "EventTimestamp": "2025-12-10T00:15:08.612Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "parallel-callbacks", + "EventTimestamp": "2025-12-10T00:15:08.643Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:15:08.643Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "branch-1-callback", + "EventTimestamp": "2025-12-10T00:15:08.643Z", + "ParentId": "ea66c06c1e1c05fa", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImY4OWExNTE3LWRmMTUtNGE3ZS1hY2U0LThjMjlhZDU0ODIzYiIsIm9wZXJhdGlvbklkIjoiMmYyMjFhMThlYjg2MzgwMyIsInRva2VuIjoiOTFlYjRiZWItN2UxOS00ZDZmLWJlMjEtNzcyMzE3N2Q4ZmMxIn0=", + "Input": {} + } + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:15:08.643Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "branch-2-callback", + "EventTimestamp": "2025-12-10T00:15:08.644Z", + "ParentId": "98c6f2c2287f4c73", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImY4OWExNTE3LWRmMTUtNGE3ZS1hY2U0LThjMjlhZDU0ODIzYiIsIm9wZXJhdGlvbklkIjoiNjE1MWY1YWIyODJkOTBlNCIsInRva2VuIjoiYmUyYzRkNzItNWU4My00YzdjLWIwMzctZTcyNDdjNTM2ZTY1In0=", + "Input": {} + } + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-10T00:15:08.644Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "branch-3-callback", + "EventTimestamp": "2025-12-10T00:15:08.644Z", + "ParentId": "13cee27a2bd93915", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImY4OWExNTE3LWRmMTUtNGE3ZS1hY2U0LThjMjlhZDU0ODIzYiIsIm9wZXJhdGlvbklkIjoiYjQyNWUwYzc1NTkxYWE4ZiIsInRva2VuIjoiNDJmYjA2YzMtYzQyZC00YTMyLWI3MzctOWZiMGE4YzlhNTZmIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 9, + "Id": "2f221a18eb863803", + "Name": "branch-1-callback", + "EventTimestamp": "2025-12-10T00:15:08.646Z", + "ParentId": "ea66c06c1e1c05fa", + "CallbackSucceededDetails": { + "Result": { + "Payload": "result-1" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 10, + "EventTimestamp": "2025-12-10T00:15:08.704Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.611Z", + "EndTimestamp": "2025-12-10T00:15:08.704Z", + "Error": {}, + "RequestId": "51316857-f314-4967-a0c0-4e044422a5ab" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 11, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:15:08.747Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"result-1\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 12, + "Id": "c4ca4238a0b92382", + "Name": "parallel-callbacks", + "EventTimestamp": "2025-12-10T00:15:08.747Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"result-1\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"index\":1,\"status\":\"STARTED\"},{\"index\":2,\"status\":\"STARTED\"}],\"completionReason\":\"MIN_SUCCESSFUL_REACHED\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 13, + "EventTimestamp": "2025-12-10T00:15:08.748Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.725Z", + "EndTimestamp": "2025-12-10T00:15:08.748Z", + "Error": {}, + "RequestId": "9b897d92-09b0-403b-bd67-1b6e5aae403e" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 14, + "Id": "51465649-ee49-44fe-bd23-8f493687450a", + "EventTimestamp": "2025-12-10T00:15:08.748Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "[\"result-1\"]" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful-with-callback/parallel-min-successful-callback.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful-with-callback/parallel-min-successful-callback.test.ts index 064329a8..e77bb95b 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful-with-callback/parallel-min-successful-callback.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful-with-callback/parallel-min-successful-callback.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should succeed when only one of three callbacks completes (minSuccessful:1)", async () => { const callback1Op = runner.getOperation("branch-1-callback"); const callback2Op = runner.getOperation("branch-2-callback"); @@ -34,6 +34,8 @@ createTests({ const results = execution.getResult() as string[]; expect(results.length).toBeGreaterThanOrEqual(1); expect(results[0]).toBe("result-1"); + + assertEventSignatures(execution); }, 10000); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful/parallel-min-successful.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful/parallel-min-successful.history.json new file mode 100644 index 00000000..a98ef183 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful/parallel-min-successful.history.json @@ -0,0 +1,285 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "fee238f4-ac65-46c1-ac85-36e8b43020b5", + "EventTimestamp": "2025-12-11T23:35:29.800Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "min-successful-branches", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "branch-1", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "branch-2", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "branch-3", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "branch-4", + "EventTimestamp": "2025-12-11T23:35:30.508Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 11, + "Id": "2f221a18eb863803", + "Name": "branch-1", + "EventTimestamp": "2025-12-11T23:35:31.211Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 1 result\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 12, + "Id": "6151f5ab282d90e4", + "Name": "branch-2", + "EventTimestamp": "2025-12-11T23:35:31.211Z", + "ParentId": "98c6f2c2287f4c73", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 2 result\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 13, + "Id": "b425e0c75591aa8f", + "Name": "branch-3", + "EventTimestamp": "2025-12-11T23:35:31.211Z", + "ParentId": "13cee27a2bd93915", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 3 result\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 14, + "Id": "a4e1cd317d54f087", + "Name": "branch-4", + "EventTimestamp": "2025-12-11T23:35:31.211Z", + "ParentId": "3a170a9fe4f47efa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 4 result\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 15, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-11T23:35:31.914Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 1 result\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 16, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-11T23:35:31.914Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 2 result\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 17, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-11T23:35:31.914Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 3 result\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 18, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-11T23:35:31.914Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 4 result\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 19, + "Id": "c4ca4238a0b92382", + "Name": "min-successful-branches", + "EventTimestamp": "2025-12-11T23:35:31.914Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"Branch 1 result\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"result\":\"Branch 2 result\",\"index\":1,\"status\":\"SUCCEEDED\"},{\"index\":2,\"status\":\"STARTED\"},{\"index\":3,\"status\":\"STARTED\"}],\"completionReason\":\"MIN_SUCCESSFUL_REACHED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 20, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-11T23:35:31.916Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-11T23:35:32.916Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 21, + "EventTimestamp": "2025-12-11T23:35:31.918Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T23:35:29.800Z", + "EndTimestamp": "2025-12-11T23:35:31.918Z", + "Error": {}, + "RequestId": "34f90178-52a1-47d4-952d-6f040d06999a" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 22, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-11T23:35:32.914Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 23, + "EventTimestamp": "2025-12-11T23:35:32.916Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T23:35:32.915Z", + "EndTimestamp": "2025-12-11T23:35:32.916Z", + "Error": {}, + "RequestId": "30002915-f777-42f3-a8d4-6faf7a4bdd6f" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 24, + "Id": "fee238f4-ac65-46c1-ac85-36e8b43020b5", + "EventTimestamp": "2025-12-11T23:35:32.916Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"successCount\":2,\"totalCount\":4,\"completionReason\":\"MIN_SUCCESSFUL_REACHED\",\"results\":[\"Branch 1 result\",\"Branch 2 result\"]}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful/parallel-min-successful.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful/parallel-min-successful.test.ts index 2d6fdd70..652b09ee 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful/parallel-min-successful.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/min-successful/parallel-min-successful.test.ts @@ -5,9 +5,10 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ localRunnerConfig: { skipTime: false, + checkpointDelay: 700, }, handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete early when minSuccessful is reached", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -30,13 +31,15 @@ createTests({ expect(branch2?.getStatus()).toBe(OperationStatus.SUCCEEDED); // TODO: Re-enable these assertions when we find the root cause of the cloud timing issue - // where remaining items show SUCCEEDED instead of STARTED + // where remaining items show SUCCEEDED instead of STARTED https://github.com/aws/aws-durable-execution-sdk-js/issues/367 // Remaining branches should be in STARTED state (not completed) // expect(branch3?.getStatus()).toBe(OperationStatus.STARTED); // expect(branch4?.getStatus()).toBe(OperationStatus.STARTED); // Verify the results array matches expect(result.results).toEqual(["Branch 1 result", "Branch 2 result"]); + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-count/parallel-tolerated-failure-count.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-count/parallel-tolerated-failure-count.history.json new file mode 100644 index 00000000..da7a97ed --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-count/parallel-tolerated-failure-count.history.json @@ -0,0 +1,350 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "2d9ce8ae-d485-4ca9-a1ef-0e11acb56f3d", + "EventTimestamp": "2025-12-10T00:12:07.576Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-count-branches", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "branch-1", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "branch-2", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "branch-3", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "branch-4", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "branch-5", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 13, + "Id": "6151f5ab282d90e4", + "Name": "branch-2", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Branch 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 14, + "Id": "a4e1cd317d54f087", + "Name": "branch-4", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "3a170a9fe4f47efa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Branch 4 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 15, + "Id": "2f221a18eb863803", + "Name": "branch-1", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 1 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "b425e0c75591aa8f", + "Name": "branch-3", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "13cee27a2bd93915", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 3 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "branch-5", + "EventTimestamp": "2025-12-10T00:12:07.586Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 5 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 18, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:07.590Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Branch 2 failed" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 19, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-10T00:12:07.590Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Branch 4 failed" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 20, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:07.590Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 1 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 21, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-10T00:12:07.590Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 3 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 22, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-10T00:12:07.590Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 5 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 23, + "Id": "c4ca4238a0b92382", + "Name": "failure-count-branches", + "EventTimestamp": "2025-12-10T00:12:07.590Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"Branch 1 success\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":1,\"status\":\"FAILED\"},{\"result\":\"Branch 3 success\",\"index\":2,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":3,\"status\":\"FAILED\"},{\"result\":\"Branch 5 success\",\"index\":4,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"ALL_COMPLETED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 24, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:07.592Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:12:08.592Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 25, + "EventTimestamp": "2025-12-10T00:12:07.645Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:07.576Z", + "EndTimestamp": "2025-12-10T00:12:07.644Z", + "Error": {}, + "RequestId": "61beea7b-4b3e-42e8-af17-5d9822fdf5e9" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 26, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:08.592Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 27, + "EventTimestamp": "2025-12-10T00:12:08.595Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:08.592Z", + "EndTimestamp": "2025-12-10T00:12:08.595Z", + "Error": {}, + "RequestId": "255263b5-25e5-4d2d-9eef-419b97adf1bf" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 28, + "Id": "2d9ce8ae-d485-4ca9-a1ef-0e11acb56f3d", + "EventTimestamp": "2025-12-10T00:12:08.595Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"successCount\":3,\"failureCount\":2,\"totalCount\":5,\"completionReason\":\"ALL_COMPLETED\",\"hasFailure\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-count/parallel-tolerated-failure-count.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-count/parallel-tolerated-failure-count.test.ts index 5c5e27cc..25044b20 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-count/parallel-tolerated-failure-count.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-count/parallel-tolerated-failure-count.test.ts @@ -4,7 +4,7 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete when failure tolerance is reached", async () => { const execution = await runner.run(); const result = execution.getResult() as any; @@ -26,6 +26,8 @@ createTests({ ].forEach(({ name, status }) => { expect(runner.getOperation(name)?.getStatus()).toBe(status); }); + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-percentage/parallel-tolerated-failure-percentage.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-percentage/parallel-tolerated-failure-percentage.history.json new file mode 100644 index 00000000..de58e53c --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-percentage/parallel-tolerated-failure-percentage.history.json @@ -0,0 +1,350 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "b70c416c-7ad8-4763-9d2e-47cc0a808e9c", + "EventTimestamp": "2025-12-10T00:12:07.533Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "Parallel", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failure-percentage-branches", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "2f221a18eb863803", + "Name": "branch-1", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "ea66c06c1e1c05fa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 6, + "Id": "6151f5ab282d90e4", + "Name": "branch-2", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "98c6f2c2287f4c73", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 7, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 8, + "Id": "b425e0c75591aa8f", + "Name": "branch-3", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "13cee27a2bd93915", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 9, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "a4e1cd317d54f087", + "Name": "branch-4", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "3a170a9fe4f47efa", + "StepStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "ParallelBranch", + "EventId": 11, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "c4ca4238a0b92382", + "ContextStartedDetails": {} + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "0f42756e5788f9b0", + "Name": "branch-5", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "12426c956d1bc501", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 13, + "Id": "6151f5ab282d90e4", + "Name": "branch-2", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "98c6f2c2287f4c73", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Branch 2 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 14, + "Id": "a4e1cd317d54f087", + "Name": "branch-4", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "3a170a9fe4f47efa", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Branch 4 failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 15, + "Id": "2f221a18eb863803", + "Name": "branch-1", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "ea66c06c1e1c05fa", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 1 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 16, + "Id": "b425e0c75591aa8f", + "Name": "branch-3", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "13cee27a2bd93915", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 3 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "0f42756e5788f9b0", + "Name": "branch-5", + "EventTimestamp": "2025-12-10T00:12:07.542Z", + "ParentId": "12426c956d1bc501", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Branch 5 success\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 18, + "Id": "98c6f2c2287f4c73", + "Name": "parallel-branch-1", + "EventTimestamp": "2025-12-10T00:12:07.547Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Branch 2 failed" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "ParallelBranch", + "EventId": 19, + "Id": "3a170a9fe4f47efa", + "Name": "parallel-branch-3", + "EventTimestamp": "2025-12-10T00:12:07.547Z", + "ParentId": "c4ca4238a0b92382", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Branch 4 failed" + } + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 20, + "Id": "ea66c06c1e1c05fa", + "Name": "parallel-branch-0", + "EventTimestamp": "2025-12-10T00:12:07.547Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 1 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 21, + "Id": "13cee27a2bd93915", + "Name": "parallel-branch-2", + "EventTimestamp": "2025-12-10T00:12:07.547Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 3 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "ParallelBranch", + "EventId": 22, + "Id": "12426c956d1bc501", + "Name": "parallel-branch-4", + "EventTimestamp": "2025-12-10T00:12:07.547Z", + "ParentId": "c4ca4238a0b92382", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"Branch 5 success\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "Parallel", + "EventId": 23, + "Id": "c4ca4238a0b92382", + "Name": "failure-percentage-branches", + "EventTimestamp": "2025-12-10T00:12:07.547Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"all\":[{\"result\":\"Branch 1 success\",\"index\":0,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":1,\"status\":\"FAILED\"},{\"result\":\"Branch 3 success\",\"index\":2,\"status\":\"SUCCEEDED\"},{\"error\":{\"cause\":{\"cause\":{\"name\":\"StepError\"},\"name\":\"StepError\",\"errorType\":\"StepError\"},\"name\":\"ChildContextError\",\"errorType\":\"ChildContextError\"},\"index\":3,\"status\":\"FAILED\"},{\"result\":\"Branch 5 success\",\"index\":4,\"status\":\"SUCCEEDED\"}],\"completionReason\":\"ALL_COMPLETED\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 24, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:07.550Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:12:08.550Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 25, + "EventTimestamp": "2025-12-10T00:12:07.602Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:07.533Z", + "EndTimestamp": "2025-12-10T00:12:07.602Z", + "Error": {}, + "RequestId": "8db03422-62dc-4df0-9b32-bac605fd0a16" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 26, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:08.548Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 27, + "EventTimestamp": "2025-12-10T00:12:08.550Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:08.549Z", + "EndTimestamp": "2025-12-10T00:12:08.550Z", + "Error": {}, + "RequestId": "4fdd45f2-3c4a-4406-b058-afe09d83f950" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 28, + "Id": "b70c416c-7ad8-4763-9d2e-47cc0a808e9c", + "EventTimestamp": "2025-12-10T00:12:08.550Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"successCount\":3,\"failureCount\":2,\"totalCount\":5,\"failurePercentage\":40,\"completionReason\":\"ALL_COMPLETED\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-percentage/parallel-tolerated-failure-percentage.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-percentage/parallel-tolerated-failure-percentage.test.ts index faaa0d94..5c3e7926 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-percentage/parallel-tolerated-failure-percentage.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/parallel/tolerated-failure-percentage/parallel-tolerated-failure-percentage.test.ts @@ -4,7 +4,7 @@ import { OperationStatus } from "@aws/durable-execution-sdk-js-testing"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete with acceptable failure percentage", async () => { const execution = await runner.run(); @@ -27,6 +27,8 @@ createTests({ ].forEach(({ name, status }) => { expect(runner.getOperation(name)?.getStatus()).toBe(status); }); + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/serde/basic/serde-basic.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/serde/basic/serde-basic.history.json new file mode 100644 index 00000000..2197517d --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/serde/basic/serde-basic.history.json @@ -0,0 +1,113 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "2e049fba-40e4-43c6-b8c3-91f610c45b7c", + "EventTimestamp": "2025-12-10T00:12:07.729Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\"}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "create-user", + "EventTimestamp": "2025-12-10T00:12:07.738Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "Name": "create-user", + "EventTimestamp": "2025-12-10T00:12:07.738Z", + "StepSucceededDetails": { + "Result": { + "Payload": "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\"}" + }, + "RetryDetails": {} + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 4, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:07.740Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:12:08.740Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 5, + "EventTimestamp": "2025-12-10T00:12:07.792Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:07.729Z", + "EndTimestamp": "2025-12-10T00:12:07.791Z", + "Error": {}, + "RequestId": "5dd0479a-bc9a-463e-8096-a7d21d35374a" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 6, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:12:08.742Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 7, + "Id": "eccbc87e4b5ce2fe", + "Name": "greet-user", + "EventTimestamp": "2025-12-10T00:12:08.744Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 8, + "Id": "eccbc87e4b5ce2fe", + "Name": "greet-user", + "EventTimestamp": "2025-12-10T00:12:08.744Z", + "StepSucceededDetails": { + "Result": { + "Payload": "\"Hello, I'm John Doe. My email is john.doe@example.com\"" + }, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:12:08.745Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:08.742Z", + "EndTimestamp": "2025-12-10T00:12:08.745Z", + "Error": {}, + "RequestId": "23ab2d54-6123-4a67-b435-07237a2c6a1d" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "2e049fba-40e4-43c6-b8c3-91f610c45b7c", + "EventTimestamp": "2025-12-10T00:12:08.745Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"user\":{\"firstName\":\"John\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\"},\"greeting\":\"Hello, I'm John Doe. My email is john.doe@example.com\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/serde/basic/serde-basic.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/serde/basic/serde-basic.test.ts index f4e15e0a..e75fa3fc 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/serde/basic/serde-basic.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/serde/basic/serde-basic.test.ts @@ -7,7 +7,7 @@ import { handler } from "./serde-basic"; createTests({ handler, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should preserve User class methods across replay with createClassSerdes", async () => { const execution = await runner.run({ payload: { @@ -57,6 +57,8 @@ createTests({ expect(result.greeting).toBe( "Hello, I'm John Doe. My email is john.doe@example.com", ); + + assertEventSignatures(execution); }); it("should work with different user data", async () => { @@ -82,6 +84,8 @@ createTests({ // This proves createClassSerdes successfully preserved the User class methods // during deserialization after the wait/replay + + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/anonymous/wait-for-callback-anonymous.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/anonymous/wait-for-callback-anonymous.history.json new file mode 100644 index 00000000..8aaf5a96 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/anonymous/wait-for-callback-anonymous.history.json @@ -0,0 +1,112 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "c954be46-0465-4285-86db-4cf750e9b3bb", + "EventTimestamp": "2025-12-10T00:15:09.611Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:09.648Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:09.648Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImRiOGE5OTIwLTJjZWUtNDE0YS1hOWFjLWM0NzY0YWQzZWRkNiIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiZGJhYWZkZmEtYjEwOS00M2VkLTljNGEtMjkzMmRlOWVlOTI2In0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:09.650Z", + "ParentId": "c4ca4238a0b92382", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"data\":\"callback_completed\"}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:09.668Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:10.717Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:10.779Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.611Z", + "EndTimestamp": "2025-12-10T00:15:10.779Z", + "Error": {}, + "RequestId": "6923bcad-b4d5-488f-b094-b2f4de03ae93" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:10.828Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"data\\\":\\\"callback_completed\\\"}\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:15:10.831Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.803Z", + "EndTimestamp": "2025-12-10T00:15:10.831Z", + "Error": {}, + "RequestId": "e0bbc1ff-2bc5-4b36-a891-c2a5fb9f5aff" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "c954be46-0465-4285-86db-4cf750e9b3bb", + "EventTimestamp": "2025-12-10T00:15:10.832Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"callbackResult\":\"{\\\"data\\\":\\\"callback_completed\\\"}\",\"completed\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/anonymous/wait-for-callback-anonymous.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/anonymous/wait-for-callback-anonymous.test.ts index 7367155f..cbd83977 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/anonymous/wait-for-callback-anonymous.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/anonymous/wait-for-callback-anonymous.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle basic waitForCallback with anonymous submitter", async () => { // Start the execution (this will pause at the callback) const executionPromise = runner.run(); @@ -33,6 +33,8 @@ createTests({ // Verify operations were tracked expect(result.getOperations().length).toBeGreaterThan(0); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-failure.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-failure.history.json new file mode 100644 index 00000000..726e660e --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-failure.history.json @@ -0,0 +1,128 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "9c5860c6-b007-4679-aa02-960bfb103fa3", + "EventTimestamp": "2025-12-10T00:15:08.871Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "my callback function", + "EventTimestamp": "2025-12-10T00:15:08.912Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:08.912Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImJlZDZjM2FmLTdiM2QtNDY1NS1hZDhhLTQ4ZjQ5MjA0YzBhZiIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiYTI5YTlhNWUtYTVlYS00MjMxLWJhYzUtOTZhMDM5NjMyYTFkIn0=", + "Timeout": 5, + "Input": {} + } + }, + { + "EventType": "CallbackFailed", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:08.913Z", + "ParentId": "c4ca4238a0b92382", + "CallbackFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "ERROR" + } + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:08.933Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:08.933Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:08.994Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.871Z", + "EndTimestamp": "2025-12-10T00:15:08.994Z", + "Error": {}, + "RequestId": "361449f1-38f7-4f4f-a4f1-880d7a0d3afb" + } + }, + { + "EventType": "ContextFailed", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "Name": "my callback function", + "EventTimestamp": "2025-12-10T00:15:09.036Z", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "ERROR" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:15:09.037Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.015Z", + "EndTimestamp": "2025-12-10T00:15:09.037Z", + "Error": { + "Payload": { + "ErrorType": "ChildContextError", + "ErrorMessage": "ERROR" + } + }, + "RequestId": "d8e44864-d425-4631-8cfa-ef8f3a70747f" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 10, + "Id": "9c5860c6-b007-4679-aa02-960bfb103fa3", + "EventTimestamp": "2025-12-10T00:15:09.037Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "ChildContextError", + "ErrorMessage": "ERROR" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-success.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-success.history.json new file mode 100644 index 00000000..e70c7ef7 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-success.history.json @@ -0,0 +1,115 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "e1dd2330-e452-4524-8f4f-2576431ff6a3", + "EventTimestamp": "2025-12-10T00:15:08.596Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "my callback function", + "EventTimestamp": "2025-12-10T00:15:08.637Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:08.638Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImQwZmNjNTQ2LTg1YTItNGZjMS05OGEwLWM3YzdmYWRkZmZhOSIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiYjE3MjkwODktOTc0YS00NTVlLWIzYmYtODJiOWUwZGFmYWMzIn0=", + "Timeout": 5, + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:08.640Z", + "ParentId": "c4ca4238a0b92382", + "CallbackSucceededDetails": { + "Result": { + "Payload": "succeeded" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:08.658Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:08.658Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:08.720Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.596Z", + "EndTimestamp": "2025-12-10T00:15:08.720Z", + "Error": {}, + "RequestId": "6d705aa0-f050-4028-b679-22cbba2d8f23" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "Name": "my callback function", + "EventTimestamp": "2025-12-10T00:15:08.763Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"succeeded\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:15:08.764Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.741Z", + "EndTimestamp": "2025-12-10T00:15:08.764Z", + "Error": {}, + "RequestId": "bf3f4e39-e7a4-47d6-8414-1d0a1d94640b" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "e1dd2330-e452-4524-8f4f-2576431ff6a3", + "EventTimestamp": "2025-12-10T00:15:08.764Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "\"succeeded\"" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-timed-out.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-timed-out.history.json new file mode 100644 index 00000000..441c5476 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback-timed-out.history.json @@ -0,0 +1,128 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "a97f0be2-220c-4b7c-99c5-8fb9d3349d93", + "EventTimestamp": "2025-12-12T00:23:39.528Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"timeoutSeconds\":1}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "my callback function", + "EventTimestamp": "2025-12-12T00:23:39.533Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-12T00:23:39.533Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjQ5Y2QzYjI5LTRhODYtNDQxZi1hNDRmLWNiZjBlZmJiNWEzNiIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiMmU5YTUwMWMtYmU1NS00ZjJlLTkzMjYtMjc4M2ZiYzhiYzcxIn0=", + "Timeout": 1, + "Input": {} + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-12T00:23:39.535Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-12T00:23:39.535Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 6, + "EventTimestamp": "2025-12-12T00:23:39.537Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:23:39.528Z", + "EndTimestamp": "2025-12-12T00:23:39.537Z", + "Error": {}, + "RequestId": "d83611bc-3327-49f0-9d78-08246956e0cb" + } + }, + { + "EventType": "CallbackTimedOut", + "SubType": "Callback", + "EventId": 7, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-12T00:23:40.536Z", + "ParentId": "c4ca4238a0b92382", + "CallbackTimedOutDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Callback timed out" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "Name": "my callback function", + "EventTimestamp": "2025-12-12T00:23:40.546Z", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "Callback timed out" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-12T00:23:40.547Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-12T00:23:40.542Z", + "EndTimestamp": "2025-12-12T00:23:40.547Z", + "Error": { + "Payload": { + "ErrorType": "ChildContextError", + "ErrorMessage": "Callback timed out" + } + }, + "RequestId": "0172677d-1faf-4949-a894-c5e96ee500eb" + } + }, + { + "EventType": "ExecutionFailed", + "EventId": 10, + "Id": "a97f0be2-220c-4b7c-99c5-8fb9d3349d93", + "EventTimestamp": "2025-12-12T00:23:40.547Z", + "ExecutionFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "ChildContextError", + "ErrorMessage": "Callback timed out" + } + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.test.ts index 41709a84..e188d34d 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner, { isCloud }) => { + tests: (runner, { assertEventSignatures }) => { it("function completes when callback succeeds - happy case", async () => { const executionPromise = runner.run(); @@ -19,6 +19,8 @@ createTests({ const execution = await executionPromise; expect(execution.getResult()).toEqual("succeeded"); + + assertEventSignatures(execution, "success"); }); it("function completes when callback fails - happy case", async () => { @@ -31,15 +33,20 @@ createTests({ const execution = await executionPromise; expect(execution.getError()).toBeDefined(); - }); - // TODO: fix testing lib local runner time scaling to handle timeouts better - if (isCloud) { - it("function times out when callback is not called - failure case", async () => { - const execution = await runner.run(); + assertEventSignatures(execution, "failure"); + }); - expect(execution.getError()).toBeDefined(); + it("function times out when callback is not called - failure case", async () => { + const execution = await runner.run({ + payload: { + timeoutSeconds: 1, + }, }); - } + + expect(execution.getError()).toBeDefined(); + + assertEventSignatures(execution, "timed-out"); + }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.ts index be305bd5..1a37cc28 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/basic/wait-for-callback.ts @@ -21,7 +21,7 @@ export const handler = withDurableExecution( "my callback function", mySubmitterFunction, { - timeout: { seconds: 5 }, + timeout: { seconds: event.timeoutSeconds ?? 5 }, }, ); log("Hello world after callback!"); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/child-context/wait-for-callback-child-context.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/child-context/wait-for-callback-child-context.history.json new file mode 100644 index 00000000..9367686e --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/child-context/wait-for-callback-child-context.history.json @@ -0,0 +1,253 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "e39cc4cc-0f5b-4a91-8775-38b3a26c2f00", + "EventTimestamp": "2025-12-10T00:15:09.667Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"test\":\"child-context-callbacks\"}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "parent-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.704Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:09.704Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjZkMzJlYmJmLTliM2EtNDc2Ni05YTM2LTZlZDBlMzk5OTM4YSIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiZDJhMTUzMmEtYWVhMy00Y2M4LTk3MjQtNmU4N2QxZTRkNDNhIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:09.705Z", + "ParentId": "c4ca4238a0b92382", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"parentData\":\"parent-completed\"}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:09.723Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:09.723Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:09.785Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.667Z", + "EndTimestamp": "2025-12-10T00:15:09.785Z", + "Error": {}, + "RequestId": "b66163d6-6deb-4777-a62d-82f20e7de3f0" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "Name": "parent-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.828Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"parentData\\\":\\\"parent-completed\\\"}\"" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "RunInChildContext", + "EventId": 9, + "Id": "c81e728d9d4c2f63", + "Name": "child-context-with-callback", + "EventTimestamp": "2025-12-10T00:15:09.828Z", + "ContextStartedDetails": {} + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 10, + "Id": "8fbdbf5573b18fae", + "Name": "child-wait", + "EventTimestamp": "2025-12-10T00:15:09.828Z", + "ParentId": "c81e728d9d4c2f63", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:15:10.828Z" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 11, + "Id": "8fbdbf5573b18fae", + "Name": "child-wait", + "EventTimestamp": "2025-12-10T00:15:09.829Z", + "ParentId": "c81e728d9d4c2f63", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 12, + "EventTimestamp": "2025-12-10T00:15:09.829Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.805Z", + "EndTimestamp": "2025-12-10T00:15:09.829Z", + "Error": {}, + "RequestId": "71857a1f-96f5-4f24-9e94-ec88d3828a35" + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 13, + "Id": "3c46a0407be60a1f", + "Name": "child-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.869Z", + "ParentId": "c81e728d9d4c2f63", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 14, + "Id": "61e70e07c25ca2dd", + "EventTimestamp": "2025-12-10T00:15:09.869Z", + "ParentId": "3c46a0407be60a1f", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjZkMzJlYmJmLTliM2EtNDc2Ni05YTM2LTZlZDBlMzk5OTM4YSIsIm9wZXJhdGlvbklkIjoiNjFlNzBlMDdjMjVjYTJkZCIsInRva2VuIjoiMTZkZTVjZmItOTZjZC00YmEyLTllYjAtNjhiZGNkY2VjOGI0In0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 15, + "Id": "61e70e07c25ca2dd", + "EventTimestamp": "2025-12-10T00:15:09.870Z", + "ParentId": "3c46a0407be60a1f", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"childData\":42}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 16, + "Id": "c2f098f784fd6490", + "EventTimestamp": "2025-12-10T00:15:09.888Z", + "ParentId": "3c46a0407be60a1f", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 17, + "Id": "c2f098f784fd6490", + "EventTimestamp": "2025-12-10T00:15:09.888Z", + "ParentId": "3c46a0407be60a1f", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 18, + "EventTimestamp": "2025-12-10T00:15:09.950Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.848Z", + "EndTimestamp": "2025-12-10T00:15:09.950Z", + "Error": {}, + "RequestId": "3e11c40b-b4cf-49bb-90f0-ac2e3958e5bb" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 19, + "Id": "3c46a0407be60a1f", + "Name": "child-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.994Z", + "ParentId": "c81e728d9d4c2f63", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"childData\\\":42}\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "RunInChildContext", + "EventId": 20, + "Id": "c81e728d9d4c2f63", + "Name": "child-context-with-callback", + "EventTimestamp": "2025-12-10T00:15:09.994Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"childResult\":\"{\\\"childData\\\":42}\",\"childProcessed\":true}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 21, + "EventTimestamp": "2025-12-10T00:15:09.994Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.971Z", + "EndTimestamp": "2025-12-10T00:15:09.994Z", + "Error": {}, + "RequestId": "7c0f94cc-e457-496c-86c8-d11c44c5a152" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 22, + "Id": "e39cc4cc-0f5b-4a91-8775-38b3a26c2f00", + "EventTimestamp": "2025-12-10T00:15:09.994Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"parentResult\":\"{\\\"parentData\\\":\\\"parent-completed\\\"}\",\"childContextResult\":{\"childResult\":\"{\\\"childData\\\":42}\",\"childProcessed\":true}}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/child-context/wait-for-callback-child-context.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/child-context/wait-for-callback-child-context.test.ts index 1ad3adaa..048af041 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/child-context/wait-for-callback-child-context.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/child-context/wait-for-callback-child-context.test.ts @@ -9,7 +9,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle waitForCallback within child contexts", async () => { // Get operations - parent callback, child context, child wait, child callback const parentCallbackOp = runner.getOperation("parent-callback-op"); @@ -52,6 +52,8 @@ createTests({ status: OperationStatus.SUCCEEDED, }); expect(completedOperations.length).toBe(8); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/failures/wait-for-callback-failures.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/failures/wait-for-callback-failures.history.json new file mode 100644 index 00000000..3a7d7cd4 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/failures/wait-for-callback-failures.history.json @@ -0,0 +1,118 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "b9117e67-76c4-453f-b9b4-136f52e60076", + "EventTimestamp": "2025-12-10T00:15:10.030Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:10.062Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:10.062Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjNiMDU4Njk2LTI3MjctNGM1Zi05MDZiLTUxZjEwMDRkNTY1ZSIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiOWEyYTdhMjYtNTc1YS00YTljLWI1ZjctNjJkNWNkMzBhMDgzIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackFailed", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:10.071Z", + "ParentId": "c4ca4238a0b92382", + "CallbackFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "External API failure", + "ErrorType": "APIException" + } + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:10.076Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:11.120Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:11.180Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.030Z", + "EndTimestamp": "2025-12-10T00:15:11.180Z", + "Error": {}, + "RequestId": "92fa7e21-950a-42c3-8356-d863115841a0" + } + }, + { + "EventType": "ContextFailed", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:15:11.220Z", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "External API failure" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:15:11.220Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:11.200Z", + "EndTimestamp": "2025-12-10T00:15:11.220Z", + "Error": {}, + "RequestId": "ac2c194a-1c2c-43c0-931f-100e2731cd30" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "b9117e67-76c4-453f-b9b4-136f52e60076", + "EventTimestamp": "2025-12-10T00:15:11.221Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"success\":false,\"error\":\"External API failure\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/failures/wait-for-callback-failures.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/failures/wait-for-callback-failures.test.ts index 7c1d87bd..b507e324 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/failures/wait-for-callback-failures.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/failures/wait-for-callback-failures.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle waitForCallback with callback failure scenarios", async () => { // Start the execution (this will pause at the callback) const executionPromise = runner.run(); @@ -33,6 +33,8 @@ createTests({ const completedOperations = result.getOperations(); expect(completedOperations.length).toEqual(3); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/heartbeat-sends/wait-for-callback-heartbeat-sends.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/heartbeat-sends/wait-for-callback-heartbeat-sends.history.json new file mode 100644 index 00000000..b742282f --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/heartbeat-sends/wait-for-callback-heartbeat-sends.history.json @@ -0,0 +1,113 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "398c39ed-5087-4e5f-84de-ea20fc7bae53", + "EventTimestamp": "2025-12-10T00:12:29.567Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"isCloud\":false}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:29.572Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:12:29.572Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6Ijk2NjIxNTY2LTIxODktNDJkNC1hMWI3LTQ1OTBhOWFmY2E1NSIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiMjE5MmIzYTItZmVjZC00ODI1LWIyNTUtMGJiOWZhZmE3YjMyIn0=", + "HeartbeatTimeout": 1, + "Input": {} + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:29.575Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:29.675Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 6, + "EventTimestamp": "2025-12-10T00:12:29.726Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:29.567Z", + "EndTimestamp": "2025-12-10T00:12:29.726Z", + "Error": {}, + "RequestId": "b4363077-0440-431c-8cae-47b1047abc66" + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 7, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:12:30.175Z", + "ParentId": "c4ca4238a0b92382", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"processed\":1000}" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:30.179Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"processed\\\":1000}\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:12:30.179Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:30.177Z", + "EndTimestamp": "2025-12-10T00:12:30.179Z", + "Error": {}, + "RequestId": "36949279-c127-43a4-8554-8b43073402ed" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "398c39ed-5087-4e5f-84de-ea20fc7bae53", + "EventTimestamp": "2025-12-10T00:12:30.179Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"callbackResult\":\"{\\\"processed\\\":1000}\",\"completed\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/heartbeat-sends/wait-for-callback-heartbeat-sends.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/heartbeat-sends/wait-for-callback-heartbeat-sends.test.ts index a6fbceff..e3d3ab5d 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/heartbeat-sends/wait-for-callback-heartbeat-sends.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/heartbeat-sends/wait-for-callback-heartbeat-sends.test.ts @@ -12,7 +12,7 @@ createTests({ localRunnerConfig: { skipTime: false, }, - tests: (runner, { isCloud }) => { + tests: (runner, { isCloud, assertEventSignatures }) => { it("should handle waitForCallback heartbeat scenarios during long-running submitter execution", async () => { const executionPromise = runner.run({ payload: { isCloud }, @@ -53,6 +53,8 @@ createTests({ status: OperationStatus.SUCCEEDED, }); expect(completedOperations.length).toBeGreaterThan(0); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/mixed-ops/wait-for-callback-mixed-ops.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/mixed-ops/wait-for-callback-mixed-ops.history.json new file mode 100644 index 00000000..e06c22e1 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/mixed-ops/wait-for-callback-mixed-ops.history.json @@ -0,0 +1,228 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "306a63fb-bb71-4c48-a20c-f42d50f446b7", + "EventTimestamp": "2025-12-10T00:15:09.246Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "initial-wait", + "EventTimestamp": "2025-12-10T00:15:09.277Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:15:10.277Z" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 3, + "Id": "c4ca4238a0b92382", + "Name": "initial-wait", + "EventTimestamp": "2025-12-10T00:15:09.278Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 4, + "EventTimestamp": "2025-12-10T00:15:09.278Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.246Z", + "EndTimestamp": "2025-12-10T00:15:09.278Z", + "Error": {}, + "RequestId": "f6e1ab7f-5851-4c2b-97b2-b9476adf5535" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "c81e728d9d4c2f63", + "Name": "fetch-user-data", + "EventTimestamp": "2025-12-10T00:15:09.322Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "c81e728d9d4c2f63", + "Name": "fetch-user-data", + "EventTimestamp": "2025-12-10T00:15:09.322Z", + "StepSucceededDetails": { + "Result": { + "Payload": "{\"userId\":123,\"name\":\"John Doe\"}" + }, + "RetryDetails": {} + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 7, + "Id": "eccbc87e4b5ce2fe", + "Name": "wait-for-callback", + "EventTimestamp": "2025-12-10T00:15:09.342Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 8, + "Id": "c9e6e7b69f98f516", + "EventTimestamp": "2025-12-10T00:15:09.343Z", + "ParentId": "eccbc87e4b5ce2fe", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImUyMzRhYjkyLThjNTItNDkxNC1hMjkwLWY3ZjY2ODY2YjAyMSIsIm9wZXJhdGlvbklkIjoiYzllNmU3YjY5Zjk4ZjUxNiIsInRva2VuIjoiMjEyODMwNjAtMDc2ZC00NmY5LTkzYWEtOTE2ZjUxYzhkZjQ2In0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 9, + "Id": "c9e6e7b69f98f516", + "EventTimestamp": "2025-12-10T00:15:09.345Z", + "ParentId": "eccbc87e4b5ce2fe", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"processed\":true}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "b772d43b49bb57b5", + "EventTimestamp": "2025-12-10T00:15:09.362Z", + "ParentId": "eccbc87e4b5ce2fe", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 11, + "Id": "b772d43b49bb57b5", + "EventTimestamp": "2025-12-10T00:15:09.467Z", + "ParentId": "eccbc87e4b5ce2fe", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 12, + "EventTimestamp": "2025-12-10T00:15:09.527Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.298Z", + "EndTimestamp": "2025-12-10T00:15:09.527Z", + "Error": {}, + "RequestId": "a32fd7f6-2436-4ee8-a2ea-09dfd118a5ee" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 13, + "Id": "eccbc87e4b5ce2fe", + "Name": "wait-for-callback", + "EventTimestamp": "2025-12-10T00:15:09.569Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"processed\\\":true}\"" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 14, + "Id": "a87ff679a2f3e71d", + "Name": "final-wait", + "EventTimestamp": "2025-12-10T00:15:09.569Z", + "WaitStartedDetails": { + "Duration": 2, + "ScheduledEndTimestamp": "2025-12-10T00:15:11.569Z" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 15, + "Id": "a87ff679a2f3e71d", + "Name": "final-wait", + "EventTimestamp": "2025-12-10T00:15:09.570Z", + "WaitSucceededDetails": { + "Duration": 2 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 16, + "EventTimestamp": "2025-12-10T00:15:09.570Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.547Z", + "EndTimestamp": "2025-12-10T00:15:09.570Z", + "Error": {}, + "RequestId": "42c5f388-4f12-42a3-a9d3-05e6171d613c" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 17, + "Id": "e4da3b7fbbce2345", + "Name": "finalize-processing", + "EventTimestamp": "2025-12-10T00:15:09.610Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 18, + "Id": "e4da3b7fbbce2345", + "Name": "finalize-processing", + "EventTimestamp": "2025-12-10T00:15:09.610Z", + "StepSucceededDetails": { + "Result": { + "Payload": "{\"status\":\"completed\",\"timestamp\":1765325711589}" + }, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 19, + "EventTimestamp": "2025-12-10T00:15:09.611Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.588Z", + "EndTimestamp": "2025-12-10T00:15:09.611Z", + "Error": {}, + "RequestId": "398dc4a0-cf48-4e10-8c4d-819bc50fa404" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 20, + "Id": "306a63fb-bb71-4c48-a20c-f42d50f446b7", + "EventTimestamp": "2025-12-10T00:15:09.611Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"stepResult\":{\"userId\":123,\"name\":\"John Doe\"},\"callbackResult\":\"{\\\"processed\\\":true}\",\"finalStep\":{\"status\":\"completed\",\"timestamp\":1765325711589},\"workflowCompleted\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/mixed-ops/wait-for-callback-mixed-ops.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/mixed-ops/wait-for-callback-mixed-ops.test.ts index aa070fab..2dad0f39 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/mixed-ops/wait-for-callback-mixed-ops.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/mixed-ops/wait-for-callback-mixed-ops.test.ts @@ -9,7 +9,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle waitForCallback mixed with steps, waits, and other operations", async () => { const callbackOperation = runner.getOperation("wait-for-callback"); @@ -44,6 +44,8 @@ createTests({ status: OperationStatus.SUCCEEDED, }); expect(completedOperations.length).toBe(7); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/multiple-invocations/wait-for-callback-multiple-invocations.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/multiple-invocations/wait-for-callback-multiple-invocations.history.json new file mode 100644 index 00000000..7f0ab556 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/multiple-invocations/wait-for-callback-multiple-invocations.history.json @@ -0,0 +1,284 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "7e96946b-8064-40a3-9775-52df4461a1a0", + "EventTimestamp": "2025-12-11T00:57:48.416Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"test\":\"multiple-invocations\"}" + } + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "wait-invocation-1", + "EventTimestamp": "2025-12-11T00:57:48.422Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-11T00:57:49.422Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 3, + "EventTimestamp": "2025-12-11T00:57:48.425Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T00:57:48.416Z", + "EndTimestamp": "2025-12-11T00:57:48.425Z", + "Error": {}, + "RequestId": "1f306733-3ca0-44fa-81e2-70c2d4d9a80d" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 4, + "Id": "c4ca4238a0b92382", + "Name": "wait-invocation-1", + "EventTimestamp": "2025-12-11T00:57:49.422Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 5, + "Id": "c81e728d9d4c2f63", + "Name": "first-callback", + "EventTimestamp": "2025-12-11T00:57:49.424Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 6, + "Id": "8fbdbf5573b18fae", + "EventTimestamp": "2025-12-11T00:57:49.424Z", + "ParentId": "c81e728d9d4c2f63", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImU0ZGVhNzBmLTk3ZmEtNDg0Yy04ZTM3LTMzOGZkM2FjZTQxYiIsIm9wZXJhdGlvbklkIjoiOGZiZGJmNTU3M2IxOGZhZSIsInRva2VuIjoiOTAwZTkyZjQtY2UzZC00ZDg5LWJiOWUtZmQxMGY2NDFhMjg5In0=", + "Input": {} + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 7, + "Id": "3c46a0407be60a1f", + "EventTimestamp": "2025-12-11T00:57:49.426Z", + "ParentId": "c81e728d9d4c2f63", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 8, + "Id": "3c46a0407be60a1f", + "EventTimestamp": "2025-12-11T00:57:49.427Z", + "ParentId": "c81e728d9d4c2f63", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 9, + "Id": "8fbdbf5573b18fae", + "EventTimestamp": "2025-12-11T00:57:49.428Z", + "ParentId": "c81e728d9d4c2f63", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"step\":1}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 10, + "EventTimestamp": "2025-12-11T00:57:49.428Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T00:57:49.422Z", + "EndTimestamp": "2025-12-11T00:57:49.428Z", + "Error": {}, + "RequestId": "4c10a9dd-5aec-411e-b797-6ecb46aa9fa6" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 11, + "Id": "c81e728d9d4c2f63", + "Name": "first-callback", + "EventTimestamp": "2025-12-11T00:57:49.431Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"step\\\":1}\"" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 12, + "Id": "eccbc87e4b5ce2fe", + "Name": "process-callback-data", + "EventTimestamp": "2025-12-11T00:57:49.432Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 13, + "Id": "eccbc87e4b5ce2fe", + "Name": "process-callback-data", + "EventTimestamp": "2025-12-11T00:57:49.432Z", + "StepSucceededDetails": { + "Result": { + "Payload": "{\"processed\":true,\"step\":1}" + }, + "RetryDetails": {} + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 14, + "Id": "a87ff679a2f3e71d", + "Name": "wait-invocation-2", + "EventTimestamp": "2025-12-11T00:57:49.433Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-11T00:57:50.433Z" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 15, + "EventTimestamp": "2025-12-11T00:57:49.435Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T00:57:49.429Z", + "EndTimestamp": "2025-12-11T00:57:49.435Z", + "Error": {}, + "RequestId": "ccc0514b-782f-4768-af1d-69c0d5d8670c" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 16, + "Id": "a87ff679a2f3e71d", + "Name": "wait-invocation-2", + "EventTimestamp": "2025-12-11T00:57:50.433Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 17, + "Id": "e4da3b7fbbce2345", + "Name": "second-callback", + "EventTimestamp": "2025-12-11T00:57:50.436Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 18, + "Id": "19a1de167122a18a", + "EventTimestamp": "2025-12-11T00:57:50.436Z", + "ParentId": "e4da3b7fbbce2345", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImU0ZGVhNzBmLTk3ZmEtNDg0Yy04ZTM3LTMzOGZkM2FjZTQxYiIsIm9wZXJhdGlvbklkIjoiMTlhMWRlMTY3MTIyYTE4YSIsInRva2VuIjoiNThhYTIzMzUtYWZkYi00N2M0LTk4NzQtY2E5NjE1ZDU5MzNmIn0=", + "Input": {} + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 19, + "Id": "dca19ffa163054fe", + "EventTimestamp": "2025-12-11T00:57:50.437Z", + "ParentId": "e4da3b7fbbce2345", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 20, + "Id": "dca19ffa163054fe", + "EventTimestamp": "2025-12-11T00:57:50.437Z", + "ParentId": "e4da3b7fbbce2345", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 21, + "Id": "19a1de167122a18a", + "EventTimestamp": "2025-12-11T00:57:50.438Z", + "ParentId": "e4da3b7fbbce2345", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"step\":2}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 22, + "EventTimestamp": "2025-12-11T00:57:50.439Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T00:57:50.433Z", + "EndTimestamp": "2025-12-11T00:57:50.439Z", + "Error": {}, + "RequestId": "bfded0ba-76dc-4900-bbcd-7abb62cff2bc" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 23, + "Id": "e4da3b7fbbce2345", + "Name": "second-callback", + "EventTimestamp": "2025-12-11T00:57:50.441Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"step\\\":2}\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 24, + "EventTimestamp": "2025-12-11T00:57:50.441Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-11T00:57:50.439Z", + "EndTimestamp": "2025-12-11T00:57:50.441Z", + "Error": {}, + "RequestId": "51b1bff4-216b-4f2f-8045-486656ba5667" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 25, + "Id": "7e96946b-8064-40a3-9775-52df4461a1a0", + "EventTimestamp": "2025-12-11T00:57:50.441Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"firstCallback\":\"{\\\"step\\\":1}\",\"secondCallback\":\"{\\\"step\\\":2}\",\"stepResult\":{\"processed\":true,\"step\":1},\"invocationCount\":\"multiple\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/multiple-invocations/wait-for-callback-multiple-invocations.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/multiple-invocations/wait-for-callback-multiple-invocations.test.ts index 97d114b9..f8931385 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/multiple-invocations/wait-for-callback-multiple-invocations.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/multiple-invocations/wait-for-callback-multiple-invocations.test.ts @@ -8,7 +8,10 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + localRunnerConfig: { + skipTime: false, + }, + tests: (runner, { assertEventSignatures }) => { it("should handle multiple invocations tracking with waitForCallback operations", async () => { // Get operations for verification const firstCallbackOp = runner.getOperation("first-callback"); @@ -39,15 +42,15 @@ createTests({ invocationCount: "multiple", }); - // Verify invocations were tracked - should be 4-5 invocations - // Due to update/termination timing, this execution may require 4-5 invocations to complete + // Verify invocations were tracked - should be exactly 5 invocations const invocations = result.getInvocations(); - expect(invocations.length).toBeGreaterThanOrEqual(4); - expect(invocations.length).toBeLessThanOrEqual(5); + expect(invocations.length).toBe(5); // Verify operations were executed const operations = result.getOperations(); expect(operations.length).toBeGreaterThan(4); // wait + callback + step + wait + callback operations + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/nested/wait-for-callback-nested.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/nested/wait-for-callback-nested.history.json new file mode 100644 index 00000000..30aead16 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/nested/wait-for-callback-nested.history.json @@ -0,0 +1,358 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "f66e69d4-c309-4df7-be6b-9164dacd1e6c", + "EventTimestamp": "2025-12-10T00:15:09.629Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "outer-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.656Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:09.656Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjJiNjM3MjA4LWUzNmEtNGFlNS04NGU3LWIxNzQ1MDc5NTg2NyIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiYzY4Njk4NjYtNjk4ZS00NzU4LTlmNTYtM2IzNmQzYjk3ODEyIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:09.657Z", + "ParentId": "c4ca4238a0b92382", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"level\":\"outer-completed\"}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:09.676Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:09.676Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:09.737Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.629Z", + "EndTimestamp": "2025-12-10T00:15:09.737Z", + "Error": {}, + "RequestId": "7d351710-35b3-4557-92b9-d04a3bae3960" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "Name": "outer-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.780Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"level\\\":\\\"outer-completed\\\"}\"" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "RunInChildContext", + "EventId": 9, + "Id": "c81e728d9d4c2f63", + "Name": "outer-child-context", + "EventTimestamp": "2025-12-10T00:15:09.780Z", + "ContextStartedDetails": {} + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 10, + "Id": "8fbdbf5573b18fae", + "Name": "inner-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.780Z", + "ParentId": "c81e728d9d4c2f63", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 11, + "Id": "de9160b4a2cf6c27", + "EventTimestamp": "2025-12-10T00:15:09.780Z", + "ParentId": "8fbdbf5573b18fae", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjJiNjM3MjA4LWUzNmEtNGFlNS04NGU3LWIxNzQ1MDc5NTg2NyIsIm9wZXJhdGlvbklkIjoiZGU5MTYwYjRhMmNmNmMyNyIsInRva2VuIjoiZjI0Y2VmZDQtNWRiMC00NDJhLWE2OTUtYzFmYzhlYjRiMTZkIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 12, + "Id": "de9160b4a2cf6c27", + "EventTimestamp": "2025-12-10T00:15:09.781Z", + "ParentId": "8fbdbf5573b18fae", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"level\":\"inner-completed\"}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 13, + "Id": "0d9f92bdd748d70d", + "EventTimestamp": "2025-12-10T00:15:09.801Z", + "ParentId": "8fbdbf5573b18fae", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 14, + "Id": "0d9f92bdd748d70d", + "EventTimestamp": "2025-12-10T00:15:09.801Z", + "ParentId": "8fbdbf5573b18fae", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 15, + "EventTimestamp": "2025-12-10T00:15:09.861Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.757Z", + "EndTimestamp": "2025-12-10T00:15:09.861Z", + "Error": {}, + "RequestId": "9f5ddc83-7ed8-491a-a760-65267b039fae" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 16, + "Id": "8fbdbf5573b18fae", + "Name": "inner-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.904Z", + "ParentId": "c81e728d9d4c2f63", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"level\\\":\\\"inner-completed\\\"}\"" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "RunInChildContext", + "EventId": 17, + "Id": "3c46a0407be60a1f", + "Name": "inner-child-context", + "EventTimestamp": "2025-12-10T00:15:09.905Z", + "ParentId": "c81e728d9d4c2f63", + "ContextStartedDetails": {} + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 18, + "Id": "61e70e07c25ca2dd", + "Name": "deep-wait", + "EventTimestamp": "2025-12-10T00:15:09.905Z", + "ParentId": "3c46a0407be60a1f", + "WaitStartedDetails": { + "Duration": 5, + "ScheduledEndTimestamp": "2025-12-10T00:15:14.905Z" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 19, + "Id": "61e70e07c25ca2dd", + "Name": "deep-wait", + "EventTimestamp": "2025-12-10T00:15:09.905Z", + "ParentId": "3c46a0407be60a1f", + "WaitSucceededDetails": { + "Duration": 5 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 20, + "EventTimestamp": "2025-12-10T00:15:09.906Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.882Z", + "EndTimestamp": "2025-12-10T00:15:09.906Z", + "Error": {}, + "RequestId": "362090dc-fb23-4727-99de-966c358a3d9e" + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 21, + "Id": "c2f098f784fd6490", + "Name": "nested-callback-op", + "EventTimestamp": "2025-12-10T00:15:09.945Z", + "ParentId": "3c46a0407be60a1f", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 22, + "Id": "1d03fc80da7b6145", + "EventTimestamp": "2025-12-10T00:15:09.945Z", + "ParentId": "c2f098f784fd6490", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjJiNjM3MjA4LWUzNmEtNGFlNS04NGU3LWIxNzQ1MDc5NTg2NyIsIm9wZXJhdGlvbklkIjoiMWQwM2ZjODBkYTdiNjE0NSIsInRva2VuIjoiZmFkNTZjNmYtZTRmNS00NzYwLTkzMDgtYzQxZGI5NzMyOTUxIn0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 23, + "Id": "1d03fc80da7b6145", + "EventTimestamp": "2025-12-10T00:15:09.946Z", + "ParentId": "c2f098f784fd6490", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"level\":\"nested-completed\"}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 24, + "Id": "8976069e5d6bb1a6", + "EventTimestamp": "2025-12-10T00:15:09.966Z", + "ParentId": "c2f098f784fd6490", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 25, + "Id": "8976069e5d6bb1a6", + "EventTimestamp": "2025-12-10T00:15:09.966Z", + "ParentId": "c2f098f784fd6490", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 26, + "EventTimestamp": "2025-12-10T00:15:10.026Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:09.922Z", + "EndTimestamp": "2025-12-10T00:15:10.026Z", + "Error": {}, + "RequestId": "f2d7cae6-9602-495a-874e-810097662393" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 27, + "Id": "c2f098f784fd6490", + "Name": "nested-callback-op", + "EventTimestamp": "2025-12-10T00:15:10.072Z", + "ParentId": "3c46a0407be60a1f", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"level\\\":\\\"nested-completed\\\"}\"" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "RunInChildContext", + "EventId": 28, + "Id": "3c46a0407be60a1f", + "Name": "inner-child-context", + "EventTimestamp": "2025-12-10T00:15:10.072Z", + "ParentId": "c81e728d9d4c2f63", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"nestedCallback\":\"{\\\"level\\\":\\\"nested-completed\\\"}\",\"deepLevel\":\"inner-child\"}" + } + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "RunInChildContext", + "EventId": 29, + "Id": "c81e728d9d4c2f63", + "Name": "outer-child-context", + "EventTimestamp": "2025-12-10T00:15:10.072Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "{\"innerCallback\":\"{\\\"level\\\":\\\"inner-completed\\\"}\",\"deepNested\":{\"nestedCallback\":\"{\\\"level\\\":\\\"nested-completed\\\"}\",\"deepLevel\":\"inner-child\"},\"level\":\"outer-child\"}" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 30, + "EventTimestamp": "2025-12-10T00:15:10.074Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.052Z", + "EndTimestamp": "2025-12-10T00:15:10.074Z", + "Error": {}, + "RequestId": "77d1ae8c-8613-4c67-8955-dab858f60b5f" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 31, + "Id": "f66e69d4-c309-4df7-be6b-9164dacd1e6c", + "EventTimestamp": "2025-12-10T00:15:10.074Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"outerCallback\":\"{\\\"level\\\":\\\"outer-completed\\\"}\",\"nestedResults\":{\"innerCallback\":\"{\\\"level\\\":\\\"inner-completed\\\"}\",\"deepNested\":{\"nestedCallback\":\"{\\\"level\\\":\\\"nested-completed\\\"}\",\"deepLevel\":\"inner-child\"},\"level\":\"outer-child\"}}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/nested/wait-for-callback-nested.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/nested/wait-for-callback-nested.test.ts index 32ce3fc2..b2b615a1 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/nested/wait-for-callback-nested.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/nested/wait-for-callback-nested.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle nested waitForCallback operations in child contexts", async () => { // Get operations - outer callback, outer context, inner callback, inner context, deep wait, nested callback const outerCallbackOp = runner.getOperation("outer-callback-op"); @@ -58,6 +58,8 @@ createTests({ // Should have tracked all operations const completedOperations = result.getOperations(); expect(completedOperations.length).toBe(12); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/serdes/wait-for-callback-serdes.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/serdes/wait-for-callback-serdes.history.json new file mode 100644 index 00000000..fa3a6b15 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/serdes/wait-for-callback-serdes.history.json @@ -0,0 +1,189 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "75f3d6bf-ca37-415d-af6f-d010babfc6ea", + "EventTimestamp": "2025-12-10T00:15:10.516Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "custom-serdes-callback", + "EventTimestamp": "2025-12-10T00:15:10.554Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:10.554Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjEwOWM2MzM3LTc5ZGQtNDFmNi05MGYxLWE4MWU5NDdiYTZmYSIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiNmNjMjM4MDMtY2QwNy00N2YxLTlkNjYtOTA3OTZlNDVlYTNjIn0=", + "Timeout": 300, + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:10.555Z", + "ParentId": "c4ca4238a0b92382", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"id\":42,\"message\":\"Hello Custom Serdes\",\"timestamp\":\"2025-06-15T12:30:45Z\",\"metadata\":{\"version\":\"2.0.0\",\"processed\":false}}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:10.575Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:10.575Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:10.637Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.516Z", + "EndTimestamp": "2025-12-10T00:15:10.637Z", + "Error": {}, + "RequestId": "0634e555-0d4e-47d6-b3c3-611339ca2ae3" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "Name": "custom-serdes-callback", + "EventTimestamp": "2025-12-10T00:15:10.680Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"id\\\":42,\\\"message\\\":\\\"Hello Custom Serdes\\\",\\\"timestamp\\\":\\\"2025-06-15T12:30:45Z\\\",\\\"metadata\\\":{\\\"version\\\":\\\"2.0.0\\\",\\\"processed\\\":false}}\"" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 9, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:15:10.680Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 10, + "Id": "c81e728d9d4c2f63", + "EventTimestamp": "2025-12-10T00:15:10.680Z", + "StepSucceededDetails": { + "Result": { + "Payload": "true" + }, + "RetryDetails": {} + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 11, + "Id": "eccbc87e4b5ce2fe", + "EventTimestamp": "2025-12-10T00:15:10.701Z", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 12, + "Id": "eccbc87e4b5ce2fe", + "EventTimestamp": "2025-12-10T00:15:10.701Z", + "StepSucceededDetails": { + "Result": { + "Payload": "true" + }, + "RetryDetails": {} + } + }, + { + "EventType": "WaitStarted", + "SubType": "Wait", + "EventId": 13, + "Id": "a87ff679a2f3e71d", + "EventTimestamp": "2025-12-10T00:15:10.722Z", + "WaitStartedDetails": { + "Duration": 1, + "ScheduledEndTimestamp": "2025-12-10T00:15:11.722Z" + } + }, + { + "EventType": "WaitSucceeded", + "SubType": "Wait", + "EventId": 14, + "Id": "a87ff679a2f3e71d", + "EventTimestamp": "2025-12-10T00:15:10.723Z", + "WaitSucceededDetails": { + "Duration": 1 + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 15, + "EventTimestamp": "2025-12-10T00:15:10.723Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.658Z", + "EndTimestamp": "2025-12-10T00:15:10.723Z", + "Error": {}, + "RequestId": "5493eaa1-a356-41c8-9f76-987552b1feba" + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 16, + "EventTimestamp": "2025-12-10T00:15:10.743Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:10.742Z", + "EndTimestamp": "2025-12-10T00:15:10.743Z", + "Error": {}, + "RequestId": "037d7bc0-b9e3-4b3b-b87e-d74f06ee5911" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 17, + "Id": "75f3d6bf-ca37-415d-af6f-d010babfc6ea", + "EventTimestamp": "2025-12-10T00:15:10.743Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"receivedData\":{\"id\":42,\"message\":\"Hello Custom Serdes\",\"timestamp\":\"2025-06-15T12:30:45.000Z\",\"metadata\":{\"version\":\"2.0.0\",\"processed\":true}},\"hasCircularReference\":true,\"isDateAfterReplay\":true,\"isDateBeforeReplay\":true,\"isSerdesProcessedBefore\":true,\"isSerdesProcessedAfter\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/serdes/wait-for-callback-serdes.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/serdes/wait-for-callback-serdes.test.ts index 7102488b..a38adb00 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/serdes/wait-for-callback-serdes.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/serdes/wait-for-callback-serdes.test.ts @@ -9,7 +9,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle waitForCallback with custom serdes configuration", async () => { const executionPromise = runner.run(); @@ -60,6 +60,8 @@ createTests({ status: OperationStatus.SUCCEEDED, }); expect(completedOperations.length).toBeGreaterThan(0); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-failure-catchable/wait-for-callback-submitter-failure-catchable.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-failure-catchable/wait-for-callback-submitter-failure-catchable.history.json new file mode 100644 index 00000000..37470321 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-failure-catchable/wait-for-callback-submitter-failure-catchable.history.json @@ -0,0 +1,180 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "a0408aae-cfa0-4909-821a-2cb9af2a770a", + "EventTimestamp": "2025-12-10T00:12:24.018Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "failing-submitter-callback", + "EventTimestamp": "2025-12-10T00:12:24.023Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:12:24.023Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6IjRkZTBmYzA2LTlkYjMtNGMxNi1iNGVjLWJmYTFkYjUzM2QyOSIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiM2I3ZWJjZDItMmNkYy00NjlhLWI4OWYtMzM4ZGU5NWEwMGEyIn0=", + "Input": {} + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:24.025Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:24.525Z", + "ParentId": "c4ca4238a0b92382", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Submitter failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 1, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 6, + "EventTimestamp": "2025-12-10T00:12:24.577Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:24.018Z", + "EndTimestamp": "2025-12-10T00:12:24.577Z", + "Error": {}, + "RequestId": "6cf15bbe-b7a4-419e-b917-4520102ba5d7" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 7, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:25.527Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 8, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:26.028Z", + "ParentId": "c4ca4238a0b92382", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Submitter failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "NextAttemptDelaySeconds": 1, + "CurrentAttempt": 1 + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:12:26.080Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:25.525Z", + "EndTimestamp": "2025-12-10T00:12:26.080Z", + "Error": {}, + "RequestId": "1f652da1-15c2-4ce2-a395-c78800314198" + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 10, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:27.032Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepFailed", + "SubType": "Step", + "EventId": 11, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:27.533Z", + "ParentId": "c4ca4238a0b92382", + "StepFailedDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Submitter failed", + "ErrorType": "Error" + } + }, + "RetryDetails": { + "CurrentAttempt": 2 + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "WaitForCallback", + "EventId": 12, + "Id": "c4ca4238a0b92382", + "Name": "failing-submitter-callback", + "EventTimestamp": "2025-12-10T00:12:27.534Z", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "StepError", + "ErrorMessage": "Submitter failed" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 13, + "EventTimestamp": "2025-12-10T00:12:27.534Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:27.030Z", + "EndTimestamp": "2025-12-10T00:12:27.534Z", + "Error": {}, + "RequestId": "8da70025-3134-42db-878f-a72e3c4c8d0a" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 14, + "Id": "a0408aae-cfa0-4909-821a-2cb9af2a770a", + "EventTimestamp": "2025-12-10T00:12:27.534Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"success\":false,\"error\":\"Submitter failed\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-failure-catchable/wait-for-callback-submitter-failure-catchable.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-failure-catchable/wait-for-callback-submitter-failure-catchable.test.ts index f464d455..338a39b8 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-failure-catchable/wait-for-callback-submitter-failure-catchable.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-failure-catchable/wait-for-callback-submitter-failure-catchable.test.ts @@ -5,7 +5,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should catch submitter failure in try-catch block", async () => { const execution = await runner.run(); @@ -15,18 +15,8 @@ createTests({ success: false, error: expect.stringContaining("Submitter failed"), }); - }); - - it("should handle submitter failure gracefully after retries", async () => { - const execution = await runner.run(); - - // Verify error is caught and returned in response - const result = execution.getResult() as any; - expect(result.success).toBe(false); - expect(result.error).toContain("Submitter failed"); - // Execution completes successfully (doesn't hang or throw unhandled error) - expect(execution.getResult()).toBeDefined(); + assertEventSignatures(execution); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-retry-success/wait-for-callback-submitter-retry-success.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-retry-success/wait-for-callback-submitter-retry-success.history.json new file mode 100644 index 00000000..14cce7e6 --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-retry-success/wait-for-callback-submitter-retry-success.history.json @@ -0,0 +1,114 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "e2067af3-c418-4d3b-96df-a5ca4e117a49", + "EventTimestamp": "2025-12-10T00:15:08.608Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"shouldFail\":false}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "Name": "retry-submitter-callback", + "EventTimestamp": "2025-12-10T00:15:08.636Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:08.636Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImU2NjQwYzRiLTllMmYtNDI1Ny1hOTAxLWUxMTZhMjUxMTg4OCIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiMjNkZWE0NTEtM2NmNC00YTkwLTg5NjctYmVlNjdhMjQ0ZjY2In0=", + "Input": {} + } + }, + { + "EventType": "CallbackSucceeded", + "SubType": "Callback", + "EventId": 4, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:15:08.641Z", + "ParentId": "c4ca4238a0b92382", + "CallbackSucceededDetails": { + "Result": { + "Payload": "{\"data\":\"completed\"}" + } + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:08.656Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 6, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:15:08.656Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 7, + "EventTimestamp": "2025-12-10T00:15:08.718Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.608Z", + "EndTimestamp": "2025-12-10T00:15:08.718Z", + "Error": {}, + "RequestId": "2b3250a6-0803-44d8-bab2-ce40cdb66d85" + } + }, + { + "EventType": "ContextSucceeded", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "Name": "retry-submitter-callback", + "EventTimestamp": "2025-12-10T00:15:08.760Z", + "ContextSucceededDetails": { + "Result": { + "Payload": "\"{\\\"data\\\":\\\"completed\\\"}\"" + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:15:08.760Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:15:08.737Z", + "EndTimestamp": "2025-12-10T00:15:08.760Z", + "Error": {}, + "RequestId": "80e9ce8f-15e1-4ac6-b75f-f2efe9b7bec9" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "e2067af3-c418-4d3b-96df-a5ca4e117a49", + "EventTimestamp": "2025-12-10T00:15:08.761Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"result\":\"{\\\"data\\\":\\\"completed\\\"}\",\"success\":true}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-retry-success/wait-for-callback-submitter-retry-success.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-retry-success/wait-for-callback-submitter-retry-success.test.ts index c1592c80..4d964ada 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-retry-success/wait-for-callback-submitter-retry-success.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/submitter-retry-success/wait-for-callback-submitter-retry-success.test.ts @@ -8,7 +8,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should complete successfully when submitter succeeds", async () => { const executionPromise = runner.run({ payload: { shouldFail: false } }); @@ -24,6 +24,8 @@ createTests({ result: JSON.stringify({ data: "completed" }), success: true, }); + + assertEventSignatures(execution); }); it("should fail after exhausting retries when submitter always fails", async () => { diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/timeout/wait-for-callback-timeout.history.json b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/timeout/wait-for-callback-timeout.history.json new file mode 100644 index 00000000..56e01aac --- /dev/null +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/timeout/wait-for-callback-timeout.history.json @@ -0,0 +1,118 @@ +[ + { + "EventType": "ExecutionStarted", + "EventId": 1, + "Id": "e1121610-07ff-4850-8c04-b98532a3bee4", + "EventTimestamp": "2025-12-10T00:12:28.109Z", + "ExecutionStartedDetails": { + "Input": { + "Payload": "{\"test\":\"timeout-scenario\"}" + } + } + }, + { + "EventType": "ContextStarted", + "SubType": "WaitForCallback", + "EventId": 2, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:28.114Z", + "ContextStartedDetails": {} + }, + { + "EventType": "CallbackStarted", + "SubType": "Callback", + "EventId": 3, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:12:28.114Z", + "ParentId": "c4ca4238a0b92382", + "CallbackStartedDetails": { + "CallbackId": "eyJleGVjdXRpb25JZCI6ImYwNmZjMDU5LWI5NTEtNDllNS05YTUwLWM5OWRmZTNhYjJjNCIsIm9wZXJhdGlvbklkIjoiZWE2NmMwNmMxZTFjMDVmYSIsInRva2VuIjoiYjE4MGEzN2EtMDdjMC00MDQ4LTlmZjktMzNiODlkNTJhNDU1In0=", + "Timeout": 1, + "Input": {} + } + }, + { + "EventType": "StepStarted", + "SubType": "Step", + "EventId": 4, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:28.116Z", + "ParentId": "c4ca4238a0b92382", + "StepStartedDetails": {} + }, + { + "EventType": "StepSucceeded", + "SubType": "Step", + "EventId": 5, + "Id": "98c6f2c2287f4c73", + "EventTimestamp": "2025-12-10T00:12:28.116Z", + "ParentId": "c4ca4238a0b92382", + "StepSucceededDetails": { + "Result": {}, + "RetryDetails": {} + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 6, + "EventTimestamp": "2025-12-10T00:12:28.168Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:28.109Z", + "EndTimestamp": "2025-12-10T00:12:28.168Z", + "Error": {}, + "RequestId": "e6aceb7f-54ec-457b-bf82-38c62b68c8ab" + } + }, + { + "EventType": "CallbackTimedOut", + "SubType": "Callback", + "EventId": 7, + "Id": "ea66c06c1e1c05fa", + "EventTimestamp": "2025-12-10T00:12:29.115Z", + "ParentId": "c4ca4238a0b92382", + "CallbackTimedOutDetails": { + "Error": { + "Payload": { + "ErrorMessage": "Callback timed out" + } + } + } + }, + { + "EventType": "ContextFailed", + "SubType": "WaitForCallback", + "EventId": 8, + "Id": "c4ca4238a0b92382", + "EventTimestamp": "2025-12-10T00:12:29.119Z", + "ContextFailedDetails": { + "Error": { + "Payload": { + "ErrorType": "CallbackError", + "ErrorMessage": "Callback timed out" + } + } + } + }, + { + "EventType": "InvocationCompleted", + "EventId": 9, + "EventTimestamp": "2025-12-10T00:12:29.119Z", + "InvocationCompletedDetails": { + "StartTimestamp": "2025-12-10T00:12:29.117Z", + "EndTimestamp": "2025-12-10T00:12:29.119Z", + "Error": {}, + "RequestId": "b40a9b97-60fe-4a61-97cf-6cf8c8b9d72a" + } + }, + { + "EventType": "ExecutionSucceeded", + "EventId": 10, + "Id": "e1121610-07ff-4850-8c04-b98532a3bee4", + "EventTimestamp": "2025-12-10T00:12:29.119Z", + "ExecutionSucceededDetails": { + "Result": { + "Payload": "{\"success\":false,\"error\":\"Callback timed out\"}" + } + } + } +] diff --git a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/timeout/wait-for-callback-timeout.test.ts b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/timeout/wait-for-callback-timeout.test.ts index be0feb45..7b6bc757 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/timeout/wait-for-callback-timeout.test.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/examples/wait-for-callback/timeout/wait-for-callback-timeout.test.ts @@ -5,7 +5,7 @@ import { createTests } from "../../../utils/test-helper"; createTests({ handler, invocationType: InvocationType.Event, - tests: (runner) => { + tests: (runner, { assertEventSignatures }) => { it("should handle waitForCallback timeout scenarios", async () => { const result = await runner.run({ payload: { test: "timeout-scenario" }, @@ -17,6 +17,8 @@ createTests({ success: false, error: expect.any(String), }); + + assertEventSignatures(result); }); }, }); diff --git a/packages/aws-durable-execution-sdk-js-examples/src/utils/test-helper.ts b/packages/aws-durable-execution-sdk-js-examples/src/utils/test-helper.ts index 07e608b7..4357412b 100644 --- a/packages/aws-durable-execution-sdk-js-examples/src/utils/test-helper.ts +++ b/packages/aws-durable-execution-sdk-js-examples/src/utils/test-helper.ts @@ -9,7 +9,7 @@ import { LocalDurableTestRunnerSetupParameters, TestResult, } from "@aws/durable-execution-sdk-js-testing"; -import { readFileSync } from "fs"; +import { existsSync, readFileSync, writeFileSync } from "fs"; import path from "path"; export interface FunctionNameMap { @@ -42,10 +42,23 @@ export interface TestDefinition { localRunnerConfig?: LocalDurableTestRunnerSetupParameters; } +export interface EventSignatureConfig { + /** + * Due to API delays or other conditions, the number of invocations can change. + * This property sets a threshold where the number of invocations in the actual history + * must be in a specified range based on the expected history. + */ + invocationCompletedDifference?: number; +} + export interface TestHelper { isTimeSkipping: boolean; isCloud: boolean; - assertEventSignatures(testResult: TestResult, suffix?: string): void; + assertEventSignatures( + testResult: TestResult, + suffix?: string, + eventSignatureConfig?: EventSignatureConfig, + ): void; functionNameMap: FunctionNameMap; } @@ -104,10 +117,34 @@ function assertEventSignatures( actualEvents: Event[], expectedEvents: EventSignature[], isTimeSkipping: boolean = false, + eventSignatureConfig?: EventSignatureConfig, ) { const actualCounts = countEventSignatures(actualEvents, isTimeSkipping); const expectedCounts = countEventSignatures(expectedEvents, isTimeSkipping); + if (eventSignatureConfig?.invocationCompletedDifference) { + const invocationCompletedSignature = JSON.stringify( + createEventSignature({ EventType: EventType.InvocationCompleted }), + ); + + const actualInvocationCompleted = actualCounts.get( + invocationCompletedSignature, + ); + actualCounts.delete(invocationCompletedSignature); + + const expectedInvocationsCompleted = expectedCounts.get( + invocationCompletedSignature, + ); + expectedCounts.delete(invocationCompletedSignature); + + const invocationCompletedDifference = Math.abs( + actualInvocationCompleted - expectedInvocationsCompleted, + ); + expect(invocationCompletedDifference).toBeLessThanOrEqual( + eventSignatureConfig.invocationCompletedDifference, + ); + } + expect(actualCounts).toEqual(expectedCounts); } @@ -139,16 +176,27 @@ function getCallerFile(): string { */ export function createTests(testDef: TestDefinition) { const isIntegrationTest = process.env.NODE_ENV === "integration"; + const generateHistories = process.env.GENERATE_HISTORY === "true"; const isTimeSkipping = (testDef.localRunnerConfig?.skipTime ?? true) && !isIntegrationTest; + if (generateHistories && isTimeSkipping && !isIntegrationTest) { + console.warn("Disabling skipTime since GENERATE_HISTORY is true"); + jest.setTimeout(120000); + } + const testFileName = getCallerFile(); const parsedFunctionName = path.basename(testFileName, ".test.ts"); + let calledAssertEventSignature = false; const testHelper: TestHelper = { - isTimeSkipping, + isTimeSkipping: isTimeSkipping && !generateHistories, isCloud: isIntegrationTest, - assertEventSignatures: (testResult: TestResult, suffix) => { + assertEventSignatures: ( + testResult: TestResult, + suffix, + eventSignatureConfig, + ) => { calledAssertEventSignature = true; const historyFileBasename = suffix @@ -159,10 +207,29 @@ export function createTests(testDef: TestDefinition) { path.dirname(testFileName), `${historyFileBasename}.history.json`, ); + + if (generateHistories) { + if (!existsSync(historyFilePath)) { + console.log(`Generated missing history for ${historyFileBasename}`); + writeFileSync( + historyFilePath, + JSON.stringify(testResult.getHistoryEvents(), null, 2), + ); + return; + } + } + + if (!existsSync(historyFilePath)) { + throw new Error( + `History file ${historyFilePath} does not exist. Please run the test with GENERATE_HISTORY=true to generate it.`, + ); + } + return assertEventSignatures( testResult.getHistoryEvents(), JSON.parse(readFileSync(historyFilePath).toString("utf-8")), testHelper.isTimeSkipping, + eventSignatureConfig, ); }, functionNameMap: isIntegrationTest @@ -172,7 +239,7 @@ export function createTests(testDef: TestDefinition) { afterAll(() => { if (!calledAssertEventSignature) { - console.warn( + throw new Error( `assertEventSignature was not called for test ${parsedFunctionName}`, ); } @@ -220,7 +287,7 @@ export function createTests(testDef: TestDefinition) { beforeAll(() => LocalDurableTestRunner.setupTestEnvironment({ ...testDef.localRunnerConfig, - skipTime: isTimeSkipping, + skipTime: testHelper.isTimeSkipping, }), ); afterAll(() => LocalDurableTestRunner.teardownTestEnvironment()); diff --git a/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/__tests__/integration/local-durable-test-runner.integration.test.ts b/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/__tests__/integration/local-durable-test-runner.integration.test.ts index 172e7556..c6270384 100644 --- a/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/__tests__/integration/local-durable-test-runner.integration.test.ts +++ b/packages/aws-durable-execution-sdk-js-testing/src/test-runner/local/__tests__/integration/local-durable-test-runner.integration.test.ts @@ -89,12 +89,9 @@ describe("LocalDurableTestRunner Integration", () => { // Verify that operations were tracked const operations = result.getOperations(); - // Verify the invocations were tracked - should be exactly 2 invocations - // Centralized termination implements a cool-down period prior to termination. - // This cool-down phase reduces the total number of invocations needed while increasing - // the number of operations performed in each invocation. + // Verify the invocations were tracked - should be exactly 3 invocations const invocations = result.getInvocations(); - expect(invocations).toHaveLength(2); + expect(invocations).toHaveLength(3); // We should have 3 operations in total expect(operations).toHaveLength(3); @@ -229,8 +226,19 @@ describe("LocalDurableTestRunner Integration", () => { }, }, { - EventType: "ExecutionSucceeded", + EventType: "InvocationCompleted", EventId: 10, + EventTimestamp: expect.any(Date), + InvocationCompletedDetails: { + StartTimestamp: expect.any(Date), + EndTimestamp: expect.any(Date), + Error: {}, + RequestId: expect.any(String), + }, + }, + { + EventType: "ExecutionSucceeded", + EventId: 11, Id: expect.any(String), EventTimestamp: expect.any(Date), ExecutionSucceededDetails: { diff --git a/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-central-termination.test.ts b/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-central-termination.test.ts index 2a96242d..fb0f2eab 100644 --- a/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-central-termination.test.ts +++ b/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-central-termination.test.ts @@ -270,7 +270,7 @@ describe("CheckpointManager - Centralized Termination", () => { ); // Advance past cooldown - jest.advanceTimersByTime(50); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).toHaveBeenCalledWith({ reason: TerminationReason.WAIT_SCHEDULED, @@ -290,8 +290,8 @@ describe("CheckpointManager - Centralized Termination", () => { }, ); - // Advance partway through cooldown - jest.advanceTimersByTime(25); + // No time advancement so the setTimeout will get cancelled from synchronous code + expect(mockTerminationManager.terminate).not.toHaveBeenCalled(); // Start new operation checkpointManager.markOperationState( @@ -306,10 +306,11 @@ describe("CheckpointManager - Centralized Termination", () => { }, ); + expect(mockTerminationManager.terminate).not.toHaveBeenCalled(); + // Advance past original cooldown - jest.advanceTimersByTime(50); + jest.advanceTimersByTime(0); - // Should not have terminated expect(mockTerminationManager.terminate).not.toHaveBeenCalled(); }); }); @@ -340,7 +341,7 @@ describe("CheckpointManager - Centralized Termination", () => { }, ); - jest.advanceTimersByTime(200); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).toHaveBeenCalledWith({ reason: TerminationReason.RETRY_SCHEDULED, @@ -372,7 +373,7 @@ describe("CheckpointManager - Centralized Termination", () => { }, ); - jest.advanceTimersByTime(200); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).toHaveBeenCalledWith({ reason: TerminationReason.WAIT_SCHEDULED, @@ -392,7 +393,7 @@ describe("CheckpointManager - Centralized Termination", () => { }, ); - jest.advanceTimersByTime(200); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).toHaveBeenCalledWith({ reason: TerminationReason.CALLBACK_PENDING, @@ -677,7 +678,7 @@ describe("CheckpointManager - Centralized Termination", () => { (checkpointManager as any).checkAndTerminate(); // Should not terminate - jest.advanceTimersByTime(300); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).not.toHaveBeenCalled(); }); @@ -701,7 +702,7 @@ describe("CheckpointManager - Centralized Termination", () => { (checkpointManager as any).checkAndTerminate(); // Should not terminate - jest.advanceTimersByTime(300); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).not.toHaveBeenCalled(); }); @@ -725,7 +726,7 @@ describe("CheckpointManager - Centralized Termination", () => { (checkpointManager as any).checkAndTerminate(); // Should not terminate - jest.advanceTimersByTime(300); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).not.toHaveBeenCalled(); }); @@ -758,7 +759,7 @@ describe("CheckpointManager - Centralized Termination", () => { (checkpointManager as any).checkAndTerminate(); // Should not terminate - jest.advanceTimersByTime(300); + jest.advanceTimersByTime(0); expect(mockTerminationManager.terminate).not.toHaveBeenCalled(); }); diff --git a/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-manager.ts b/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-manager.ts index dd79cd53..211c0973 100644 --- a/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-manager.ts +++ b/packages/aws-durable-execution-sdk-js/src/utils/checkpoint/checkpoint-manager.ts @@ -51,7 +51,6 @@ export class CheckpointManager implements Checkpoint { // Termination cooldown private terminationTimer: NodeJS.Timeout | null = null; private terminationReason: TerminationReason | null = null; - private readonly TERMINATION_COOLDOWN_MS = 50; constructor( private durableExecutionArn: string, @@ -714,12 +713,12 @@ export class CheckpointManager implements Checkpoint { this.terminationReason = reason; log("⏱️", "Scheduling termination", { reason, - cooldownMs: this.TERMINATION_COOLDOWN_MS, }); + // Schedule termination immediately once event loop is free. this.terminationTimer = setTimeout(() => { this.executeTermination(reason); - }, this.TERMINATION_COOLDOWN_MS); + }, 0); } private executeTermination(reason: TerminationReason): void {