| 1 | import * as Lambda from "@/AWS/Lambda"; |
| 2 | import * as Duration from "effect/Duration"; |
| 3 | import * as Effect from "effect/Effect"; |
| 4 | import path from "pathe"; |
| 5 | |
| 6 | const main = path.resolve(import.meta.dirname, "durable-handler.ts"); |
| 7 | |
| 8 | /** |
| 9 | * A three-operation durable orchestration: two checkpointed steps around a |
| 10 | * durable sleep. The sleep suspends the execution (the invocation returns |
| 11 | * PENDING) and Lambda re-invokes the function to resume, so a SUCCEEDED |
| 12 | * result proves the full checkpoint/replay round-trip: |
| 13 | * invoke #1 — step "reserve" checkpoints, wait checkpoints, suspend |
| 14 | * invoke #2 — replay memoizes "reserve", runs "price", completes |
| 15 | * |
| 16 | * A DurableFunction IS the Lambda function (wrapper of AWS.Lambda.Function): |
| 17 | * the wrapper sets `DurableConfig` at create time, disables the Function URL, |
| 18 | * self-binds the checkpoint-protocol IAM, and vendors |
| 19 | * `@aws/durable-execution-sdk-js` into the artifact automatically. |
| 20 | */ |
| 21 | export class DurableFlow extends Lambda.DurableFunction<DurableFlow>()( |
| 22 | "DurableFlow", |
| 23 | ) {} |
| 24 | |
| 25 | export default DurableFlow.make( |
| 26 | { |
| 27 | main, |
| 28 | executionTimeout: Duration.hours(1), |
| 29 | retentionPeriod: "1 day", |
| 30 | // Per-invocation budget (each resume is its own invocation). |
| 31 | timeout: Duration.seconds(60), |
| 32 | }, |
| 33 | Effect.gen(function* () { |
| 34 | return Effect.fn(function* (input: { orderId: string }) { |
| 35 | const reserved = yield* Lambda.Durable.step( |
| 36 | "reserve", |
| 37 | Effect.succeed({ orderId: input.orderId, reserved: true }), |
| 38 | ); |
| 39 | yield* Lambda.Durable.sleep("cooldown", "5 seconds"); |
| 40 | const total = yield* Lambda.Durable.step( |
| 41 | "price", |
| 42 | // Non-deterministic work belongs inside a step: the checkpointed |
| 43 | // result replays identically on the resume invocation. |
| 44 | Effect.sync(() => 40 + 2), |
| 45 | ); |
| 46 | return { orderId: reserved.orderId, reserved: reserved.reserved, total }; |
| 47 | }); |
| 48 | }), |
| 49 | ); |