From 0c58900c20767a3b54cc00aae6d7a8d22a299c6b Mon Sep 17 00:00:00 2001 From: Rishi Tiwari Date: Sat, 16 May 2026 16:22:39 +0530 Subject: [PATCH 1/2] fix semantics --- .../steering/advanced-patterns.md | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/aws-lambda-durable-functions-power/steering/advanced-patterns.md b/aws-lambda-durable-functions-power/steering/advanced-patterns.md index fb53b8b..734ecf3 100644 --- a/aws-lambda-durable-functions-power/steering/advanced-patterns.md +++ b/aws-lambda-durable-functions-power/steering/advanced-patterns.md @@ -105,28 +105,33 @@ def handler(event: dict, context: DurableContext) -> str: ```typescript import { StepSemantics } from '@aws/durable-execution-sdk-js'; -// AtMostOncePerRetry - For non-idempotent operations -// Step executes at most once per retry attempt -// If step fails partway through, it won't re-execute the same attempt +// AtLeastOncePerRetry (DEFAULT) - For operations that can execute multiple times +// Step may execute multiple times per retry attempt +// Use when idempotency is handled externally await context.step( 'update-database', async () => { // This is idempotent - safe to retry return await updateUserRecord(userId, data); }, - { semantics: StepSemantics.AtMostOncePerRetry } + { semantics: StepSemantics.AtLeastOncePerRetry } ); -// AtLeastOncePerRetry (DEFAULT) - For operations that can execute multiple times -// Step may execute multiple times per retry attempt -// Use when idempotency is handled externally +// AtMostOncePerRetry - For non-idempotent operations +// Step executes at most once per retry attempt +// If step fails partway through, it won't re-execute the same attempt await context.step( - 'send-notification', + 'charge-payment', async () => { - // External system handles deduplication - return await sendEmail(email, message); + // Non-idempotent - duplicates would double-charge the customer + return await chargePayment(customerId, amount); }, - { semantics: StepSemantics.AtLeastOncePerRetry } + { + semantics: StepSemantics.AtMostOncePerRetry, + // Pair with shouldRetry: false to guarantee at-most-once overall, + // since the default retry strategy still allows multiple retry attempts. + retryStrategy: () => ({ shouldRetry: false }), + } ); ``` From bfe2928f0846507cf5788452ed42b66d825f89d9 Mon Sep 17 00:00:00 2001 From: Rishi Tiwari Date: Sat, 16 May 2026 16:42:58 +0530 Subject: [PATCH 2/2] semantics fix --- .../steering/step-operations.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aws-lambda-durable-functions-power/steering/step-operations.md b/aws-lambda-durable-functions-power/steering/step-operations.md index f32316e..911b2d8 100644 --- a/aws-lambda-durable-functions-power/steering/step-operations.md +++ b/aws-lambda-durable-functions-power/steering/step-operations.md @@ -186,9 +186,9 @@ retry_config = RetryStrategyConfig( ## Step Semantics -### AT_LEAST_ONCE (Default) +### AtLeastOncePerRetry (default) -Step executes at least once, may execute multiple times on failure/retry. +Step executes at least once on each retry attempt. If the step succeeds but the checkpoint fails (e.g. due to a sandbox crash), the step will re-execute on replay. Use for idempotent operations that can tolerate duplicate execution. **TypeScript:** @@ -202,9 +202,9 @@ const result = await context.step( ); ``` -### AT_MOST_ONCE +### AtMostOncePerRetry -Step executes at most once, never retries. Use for non-idempotent operations. +Step executes at most once per retry attempt. If a crash happens between the pre-step checkpoint and step completion, the step is skipped on replay rather than re-executed. The step can still run across multiple retry attempts. To guarantee at-most-once overall, pair with `retryStrategy: () => ({ shouldRetry: false })`. **TypeScript:** @@ -360,4 +360,4 @@ except Exception as error: 4. **Use appropriate retry strategies** based on operation type 5. **Handle errors explicitly** - don't let them propagate unexpectedly 6. **Use custom serialization** for complex types -7. **Choose correct semantics** (AT_LEAST_ONCE vs AT_MOST_ONCE) +7. **Choose correct semantics** (`AtLeastOncePerRetry` vs `AtMostOncePerRetry`)