You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Lambda->>Persistence Layer: Get or set (id=event.search(payload))
367
+
activate Persistence Layer
368
+
Note right of Persistence Layer: Locked to prevent concurrent<br/>invocations with <br/> the same payload.
369
+
Lambda-->>Lambda: Call handler (event)
370
+
Lambda->>Persistence Layer: Update record with result
371
+
deactivate Persistence Layer
372
+
Persistence Layer-->>Persistence Layer: Update record with result
373
+
Lambda-->>Client: Response sent to client
374
+
else retried request
375
+
Client->>Lambda: Invoke (event)
376
+
Lambda->>Persistence Layer: Get or set (id=event.search(payload))
377
+
Persistence Layer-->>Lambda: Already exists in persistence layer. Return result
378
+
Lambda-->>Client: Response sent to client
379
+
end
380
+
```
381
+
<i>Idempotent sequence</i>
382
+
</center>
359
383
360
384
The client was successful in receiving the result after the retry. Since the Lambda handler was only executed once, our customer hasn't been charged twice.
361
385
362
386
!!! note
363
387
Bear in mind that the entire Lambda handler is treated as a single idempotent operation. If your Lambda handler can cause multiple side effects, consider splitting it into separate functions.
364
388
389
+
#### Lambda timeouts
390
+
391
+
This is automatically done when you annotate your Lambda handler with [@Idempotent annotation](#idempotent-annotation).
392
+
393
+
To prevent against extended failed retries when a [Lambda function times out](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-verify-invocation-timeouts/), Powertools calculates and includes the remaining invocation available time as part of the idempotency record.
394
+
395
+
!!! example
396
+
If a second invocation happens **after** this timestamp, and the record is marked as `INPROGRESS`, we will execute the invocation again as if it was in the `EXPIRED` state.
397
+
This means that if an invocation expired during execution, it will be quickly executed again on the next retry.
398
+
399
+
!!! important
400
+
If you are using the [@Idempotent annotation on another method](#idempotent-annotation-on-another-method) to guard isolated parts of your code, you must use `registerLambdaContext` method available in the `Idempotency` object to benefit from this protection.
401
+
402
+
Here is an example on how you register the Lambda context in your handler:
403
+
404
+
```java hl_lines="13-19" title="Registering the Lambda context"
405
+
public class PaymentHandler implements RequestHandler<SQSEvent, List<String>> {
Lambda->>Persistence Layer: Get or set (id=event.search(payload))
459
+
activate Persistence Layer
460
+
Note right of Persistence Layer: Locked to prevent concurrent<br/>invocations with <br/> the same payload.
461
+
Lambda-->>Lambda: Call handler (event)
462
+
Lambda->>Persistence Layer: Update record with result
463
+
deactivate Persistence Layer
464
+
Persistence Layer-->>Persistence Layer: Update record with result
465
+
Lambda-->>Client: Response sent to client
466
+
end
467
+
```
468
+
<i>Idempotent sequence for Lambda timeouts</i>
469
+
</center>
470
+
365
471
### Handling exceptions
366
472
367
473
If you are using the `@Idempotent` annotation on your Lambda handler or any other method, any unhandled exceptions that are thrown during the code execution will cause **the record in the persistence layer to be deleted**.
368
474
This means that new invocations will execute your code again despite having the same payload. If you don't want the record to be deleted, you need to catch exceptions within the idempotent function and return a successful response.
Lambda->>Persistence Layer: Delete record (id=event.search(payload))
488
+
deactivate Persistence Layer
489
+
Lambda-->>Client: Return error response
490
+
```
491
+
<i>Idempotent sequence exception</i>
492
+
</center>
371
493
372
494
If an Exception is raised _outside_ the scope of a decorated method and after your method has been called, the persistent record will not be affected. In this case, idempotency will be maintained for your decorated function. Example:
Copy file name to clipboardExpand all lines: powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java
+1-1
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,7 @@
15
15
16
16
/**
17
17
* IdempotencyInconsistentStateException can happen under rare but expected cases
18
-
* when persistent state changes in the small-time between put & get requests.
18
+
* when persistent state changes in the small-time between put & get requests.
Copy file name to clipboardExpand all lines: powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java
Copy file name to clipboardExpand all lines: powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java
thrownewIdempotencyConfigurationException("Unable to get payload from the method. Ensure there is at least one parameter or that you use @IdempotencyKey");
0 commit comments