@@ -168,7 +168,7 @@ You can use `data_keyword_argument` to tell us the argument to extract an idempo
168
168
169
169
=== "Using Dataclasses"
170
170
171
- ```python title="working_with_idempotent_function_dataclass.py" hl_lines="3-7 11 26 39 "
171
+ ```python title="working_with_idempotent_function_dataclass.py" hl_lines="4-8 12 28 41 "
172
172
--8<-- "examples/idempotency/src/working_with_idempotent_function_dataclass.py"
173
173
```
174
174
@@ -178,7 +178,7 @@ You can use `data_keyword_argument` to tell us the argument to extract an idempo
178
178
179
179
=== "Using Pydantic"
180
180
181
- ```python title="working_with_idempotent_function_pydantic.py" hl_lines="1-5 10 23 34 "
181
+ ```python title="working_with_idempotent_function_pydantic.py" hl_lines="3-7 12 26 37 "
182
182
--8<-- "examples/idempotency/src/working_with_idempotent_function_pydantic.py"
183
183
```
184
184
@@ -196,7 +196,7 @@ The output serializer supports any JSON serializable data, **Python Dataclasses*
196
196
197
197
=== "Inferring via the return type"
198
198
199
- ```python hl_lines="6 24 25 32 36 45 "
199
+ ```python hl_lines="8 27 35 38 48 "
200
200
--8<-- "examples/idempotency/src/working_with_pydantic_deduced_output_serializer.py"
201
201
```
202
202
@@ -206,7 +206,7 @@ The output serializer supports any JSON serializable data, **Python Dataclasses*
206
206
207
207
Alternatively, you can provide an explicit model as an input to `PydanticSerializer`.
208
208
209
- ```python hl_lines="6 24 25 32 35 44 "
209
+ ```python hl_lines="8 27 35 35 47 "
210
210
--8<-- "examples/idempotency/src/working_with_pydantic_explicitly_output_serializer.py"
211
211
```
212
212
@@ -216,7 +216,7 @@ The output serializer supports any JSON serializable data, **Python Dataclasses*
216
216
217
217
=== "Inferring via the return type"
218
218
219
- ```python hl_lines="8 27-29 36 40 49 "
219
+ ```python hl_lines="9 30 38 41 51 "
220
220
--8<-- "examples/idempotency/src/working_with_dataclass_deduced_output_serializer.py"
221
221
```
222
222
@@ -226,7 +226,7 @@ The output serializer supports any JSON serializable data, **Python Dataclasses*
226
226
227
227
Alternatively, you can provide an explicit model as an input to `DataclassSerializer`.
228
228
229
- ```python hl_lines="8 27-29 36 39 48 "
229
+ ```python hl_lines="8 30 38 40 50 "
230
230
--8<-- "examples/idempotency/src/working_with_dataclass_explicitly_output_serializer.py"
231
231
```
232
232
@@ -237,7 +237,7 @@ The output serializer supports any JSON serializable data, **Python Dataclasses*
237
237
* **to_dict**. Function to convert any type to a JSON serializable dictionary before it saves into the persistent storage.
238
238
* **from_dict**. Function to convert from a dictionary retrieved from persistent storage and serialize in its original form.
239
239
240
- ```python hl_lines="8 32 36 40 50 53 "
240
+ ```python hl_lines="9 34 38 42 52 54 64 "
241
241
--8<-- "examples/idempotency/src/working_with_idempotent_function_custom_output_serializer.py"
242
242
```
243
243
@@ -255,7 +255,7 @@ By default, caching is disabled since we don't know how big your response could
255
255
256
256
=== "Enabling cache"
257
257
258
- ```python hl_lines="12 "
258
+ ```python hl_lines="15 "
259
259
--8<-- "examples/idempotency/src/working_with_local_cache.py"
260
260
```
261
261
@@ -290,7 +290,7 @@ Imagine the function runs successfully, but the client never receives the respon
290
290
291
291
=== "Payment function"
292
292
293
- ```python hl_lines="5-9 16 30 "
293
+ ```python hl_lines="6-10 18 31 "
294
294
--8<-- "examples/idempotency/src/working_with_payload_subset.py"
295
295
```
296
296
@@ -308,8 +308,14 @@ Imagine the function runs successfully, but the client never receives the respon
308
308
To prevent against extended failed retries when a [ Lambda function times out] ( https://aws.amazon.com/premiumsupport/knowledge-center/lambda-verify-invocation-timeouts/ ) {target="_ blank"},
309
309
Powertools for AWS Lambda (Python) calculates and includes the remaining invocation available time as part of the idempotency record.
310
310
311
- ???+ example
312
- 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 (e.g, ` expire_seconds ` field elapsed).
311
+ To prevent extended failures, use ** ` register_lambda_context ` ** function from your idempotency config to calculate and include the remaining invocation time in your idempotency record.
312
+
313
+ ``` python title="working_with_lambda_timeout.py" hl_lines="14 23"
314
+ -- 8 < -- " examples/idempotency/src/working_with_lambda_timeout.py"
315
+ ```
316
+
317
+ ???+ example "Mechanics"
318
+ If a second invocation happens ** after** this timestamp, and the record is marked as ` INPROGRESS ` , we will run the invocation again as if it was in the ` EXPIRED ` state.
313
319
314
320
This means that if an invocation expired during execution, it will be quickly executed again on the next retry.
315
321
@@ -344,7 +350,9 @@ If an exception is handled or raised **outside** your decorated function, then i
344
350
345
351
This persistence layer is built-in, allowing you to use an existing DynamoDB table or create a new one dedicated to idempotency state (recommended).
346
352
347
- === "Customizing DynamoDBPersistenceLayer to suit your table structure"
353
+ ``` python title="customize_persistence_layer.py" hl_lines="10-18"
354
+ -- 8 < -- " examples/idempotency/src/customize_persistence_layer.py"
355
+ ```
348
356
349
357
```python hl_lines="7-15"
350
358
--8<-- "examples/idempotency/src/customize_persistence_layer.py"
@@ -375,12 +383,12 @@ For a quick start, initialize `RedisCachePersistenceLayer` and pass your cluster
375
383
For security, we enforce SSL connections by default; to disable it, set ` ssl=False ` .
376
384
377
385
=== "Redis quick start"
378
- ```python hl_lines="7-9 12 26 "
386
+ ```python title="getting_started_with_idempotency_redis_config.py" hl_lines="8-10 14 27 "
379
387
--8<-- "examples/idempotency/src/getting_started_with_idempotency_redis_config.py"
380
388
```
381
389
382
390
=== "Using an existing Redis client"
383
- ```python hl_lines="4 9 -11 14 22 36 "
391
+ ```python title="getting_started_with_idempotency_redis_client.py" hl_lines="5 10 -11 16 24 38 "
384
392
--8<-- "examples/idempotency/src/getting_started_with_idempotency_redis_client.py"
385
393
```
386
394
@@ -438,11 +446,9 @@ You can customize attribute names when instantiating `RedisCachePersistenceLayer
438
446
| ** data_attr** | | ` data ` | Stores results of successfully executed Lambda handlers |
439
447
| ** validation_key_attr** | | ` validation ` | Hashed representation of the parts of the event used for validation |
440
448
441
- === "Customizing RedisPersistenceLayer to suit your data structure"
442
-
443
- ```python hl_lines="9-16"
444
- --8<-- "examples/idempotency/src/customize_persistence_layer_redis.py"
445
- ```
449
+ ``` python title="customize_persistence_layer_redis.py" hl_lines="15-18"
450
+ -- 8 < -- " examples/idempotency/src/customize_persistence_layer_redis.py"
451
+ ```
446
452
447
453
### Common use cases
448
454
@@ -777,7 +783,7 @@ You can change this window with the **`expires_after_seconds`** parameter:
777
783
778
784
=== "Adjusting idempotency record expiration"
779
785
780
- ```python hl_lines="11 "
786
+ ```python hl_lines="14 "
781
787
--8<-- "examples/idempotency/src/working_with_record_expiration.py"
782
788
```
783
789
@@ -811,7 +817,7 @@ With **`payload_validation_jmespath`**, you can provide an additional JMESPath e
811
817
812
818
=== "Payload validation"
813
819
814
- ```python hl_lines="12 20 28 "
820
+ ```python hl_lines="16 25 32 "
815
821
--8<-- "examples/idempotency/src/working_with_validation_payload.py"
816
822
```
817
823
@@ -847,7 +853,7 @@ This means that we will raise **`IdempotencyKeyError`** if the evaluation of **`
847
853
848
854
=== "Idempotency key required"
849
855
850
- ```python hl_lines="11 "
856
+ ```python hl_lines="14 "
851
857
--8<-- "examples/idempotency/src/working_with_idempotency_key_required.py"
852
858
```
853
859
@@ -869,13 +875,13 @@ The **`boto_config`** and **`boto3_session`** parameters enable you to pass in a
869
875
870
876
=== "Custom session"
871
877
872
- ```python hl_lines="1 11 13 "
878
+ ```python hl_lines="3 13 16 "
873
879
--8<-- "examples/idempotency/src/working_with_custom_session.py"
874
880
```
875
881
876
882
=== "Custom config"
877
883
878
- ```python hl_lines="1 11 13 "
884
+ ```python hl_lines="3 13 16 "
879
885
--8<-- "examples/idempotency/src/working_with_custom_config.py"
880
886
```
881
887
@@ -895,7 +901,7 @@ You can optionally set a static value for the partition key using the `static_pk
895
901
896
902
=== "Reusing a DynamoDB table that uses a composite primary key"
897
903
898
- ```python hl_lines="7 "
904
+ ```python hl_lines="10 "
899
905
--8<-- "examples/idempotency/src/working_with_composite_key.py"
900
906
```
901
907
@@ -924,11 +930,9 @@ You can create your own persistent store from scratch by inheriting the `BasePer
924
930
* ** ` _update_record() ` ** – Updates an item in the persistence store.
925
931
* ** ` _delete_record() ` ** – Removes an item from the persistence store.
926
932
927
- === "Bring your own persistent store"
928
-
929
- ```python hl_lines="8 18 65 74 96 124"
930
- --8<-- "examples/idempotency/src/bring_your_own_persistent_store.py"
931
- ```
933
+ ``` python title="bring_your_own_persistent_store.py" hl_lines="8 18 65 74 96 124"
934
+ -- 8 < -- " examples/idempotency/src/bring_your_own_persistent_store.py"
935
+ ```
932
936
933
937
???+ danger
934
938
Pay attention to the documentation for each - you may need to perform additional checks inside these methods to ensure the idempotency guarantees remain intact.
@@ -941,7 +945,7 @@ You can set up a `response_hook` in the `IdempotentConfig` class to manipulate t
941
945
942
946
=== "Using an Idempotent Response Hook"
943
947
944
- ```python hl_lines="19 21 27 34 "
948
+ ```python hl_lines="20 22 28 36 "
945
949
--8<-- "examples/idempotency/src/working_with_response_hook.py"
946
950
```
947
951
@@ -971,7 +975,7 @@ When using response hooks to manipulate returned data from idempotent operations
971
975
972
976
See [ Batch integration] ( #batch-integration ) above.
973
977
974
- ### Validation utility
978
+ ### JSON Schema Validation
975
979
976
980
The idempotency utility can be used with the ` validator ` decorator. Ensure that idempotency is the innermost decorator.
977
981
@@ -983,7 +987,7 @@ The idempotency utility can be used with the `validator` decorator. Ensure that
983
987
984
988
=== "Using Idempotency with JSONSchema Validation utility"
985
989
986
- ```python hl_lines="13 "
990
+ ```python hl_lines="16 "
987
991
--8<-- "examples/idempotency/src/integrate_idempotency_with_validator.py"
988
992
```
989
993
0 commit comments