Skip to content

Commit 5f27b2b

Browse files
committed
docs: document new idempotent_function
1 parent 661faf8 commit 5f27b2b

File tree

1 file changed

+78
-2
lines changed

1 file changed

+78
-2
lines changed

docs/utilities/idempotency.md

+78-2
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,83 @@ You can quickly start by initializing the `DynamoDBPersistenceLayer` class and u
121121
}
122122
```
123123

124-
#### Choosing a payload subset for idempotency
124+
### Idempotent_function decorator
125+
126+
Similar to [idempotent decorator](#idempotent-decorator), you can use `idempotent_function` decorator for any synchronous Python function.
127+
128+
When using `idempotent_function`, you must tell us which keyword parameter in your function signature has the data we should use via **`data_keyword_argument`** - Such data must be JSON serializable.
129+
130+
131+
132+
!!! warning "Make sure to call your decorated function using keyword arguments"
133+
134+
=== "app.py"
135+
136+
This example also demonstrates how you can integrate with [Batch utility](batch.md), so you can process each record in an idempotent manner.
137+
138+
```python hl_lines="4 13 18 25"
139+
import uuid
140+
141+
from aws_lambda_powertools.utilities.batch import sqs_batch_processor
142+
from aws_lambda_powertools.utilities.idempotency import idempotent_function, DynamoDBPersistenceLayer, IdempotencyConfig
143+
144+
145+
dynamodb = DynamoDBPersistenceLayer(table_name="idem")
146+
config = IdempotencyConfig(
147+
event_key_jmespath="messageId", # see "Choosing a payload subset for idempotency" section
148+
use_local_cache=True,
149+
)
150+
151+
@idempotent_function(data_keyword_argument="data", config=config, persistence_store=dynamodb)
152+
def dummy(arg_one, arg_two, data: dict, **kwargs):
153+
return {"data": data}
154+
155+
156+
@idempotent_function(data_keyword_argument="record", config=config, persistence_store=dynamodb)
157+
def record_handler(record):
158+
return {"message": record["body"]}
159+
160+
161+
@sqs_batch_processor(record_handler=record_handler)
162+
def lambda_handler(event, context):
163+
# `data` parameter must be called as a keyword argument to work
164+
dummy("hello", "universe", data="test")
165+
return {"statusCode": 200}
166+
```
167+
168+
=== "Example event"
169+
170+
```json hl_lines="4"
171+
{
172+
"Records": [
173+
{
174+
"messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
175+
"receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
176+
"body": "Test message.",
177+
"attributes": {
178+
"ApproximateReceiveCount": "1",
179+
"SentTimestamp": "1545082649183",
180+
"SenderId": "AIDAIENQZJOLO23YVJ4VO",
181+
"ApproximateFirstReceiveTimestamp": "1545082649185"
182+
},
183+
"messageAttributes": {
184+
"testAttr": {
185+
"stringValue": "100",
186+
"binaryValue": "base64Str",
187+
"dataType": "Number"
188+
}
189+
},
190+
"md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
191+
"eventSource": "aws:sqs",
192+
"eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue",
193+
"awsRegion": "us-east-2"
194+
}
195+
]
196+
}
197+
```
198+
199+
200+
### Choosing a payload subset for idempotency
125201

126202
!!! tip "Dealing with always changing payloads"
127203
When dealing with a more elaborate payload, where parts of the payload always change, you should use **`event_key_jmespath`** parameter.
@@ -198,7 +274,7 @@ Imagine the function executes successfully, but the client never receives the re
198274
}
199275
```
200276

201-
#### Idempotency request flow
277+
### Idempotency request flow
202278

203279
This sequence diagram shows an example flow of what happens in the payment scenario:
204280

0 commit comments

Comments
 (0)