Skip to content

Commit 676befd

Browse files
committed
docs(idempotency): document new formats
1 parent 0c8a2d4 commit 676befd

File tree

1 file changed

+95
-17
lines changed

1 file changed

+95
-17
lines changed

docs/utilities/idempotency.md

Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -124,45 +124,50 @@ You can quickly start by initializing the `DynamoDBPersistenceLayer` class and u
124124

125125
Similar to [idempotent decorator](#idempotent-decorator), you can use `idempotent_function` decorator for any synchronous Python function.
126126

127-
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.
127+
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`**.
128+
129+
!!! info "We support JSON serializable data, [Python Dataclasses](https://docs.python.org/3.7/library/dataclasses.html){target="_blank"}, [Parser/Pydantic Models](parser.md){target="_blank"}, and our [Event Source Data Classes](./data_classes.md){target="_blank"}."
128130

129131
!!! warning "Make sure to call your decorated function using keyword arguments"
130132

131-
=== "app.py"
133+
=== "batch_sample.py"
132134

133135
This example also demonstrates how you can integrate with [Batch utility](batch.md), so you can process each record in an idempotent manner.
134136

135-
```python hl_lines="4 13 18 25"
136-
import uuid
137-
138-
from aws_lambda_powertools.utilities.batch import sqs_batch_processor
139-
from aws_lambda_powertools.utilities.idempotency import idempotent_function, DynamoDBPersistenceLayer, IdempotencyConfig
137+
```python hl_lines="4-5 16 21 29"
138+
from aws_lambda_powertools.utilities.batch import (BatchProcessor, EventType,
139+
batch_processor)
140+
from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord
141+
from aws_lambda_powertools.utilities.idempotency import (
142+
DynamoDBPersistenceLayer, IdempotencyConfig, idempotent_function)
140143

141144

145+
processor = BatchProcessor(event_type=EventType.SQS)
142146
dynamodb = DynamoDBPersistenceLayer(table_name="idem")
143147
config = IdempotencyConfig(
144-
event_key_jmespath="messageId", # see "Choosing a payload subset for idempotency" section
148+
event_key_jmespath="messageId", # see Choosing a payload subset section
145149
use_local_cache=True,
146150
)
147151

148-
@idempotent_function(data_keyword_argument="data", config=config, persistence_store=dynamodb)
149-
def dummy(arg_one, arg_two, data: dict, **kwargs):
150-
return {"data": data}
151-
152152

153153
@idempotent_function(data_keyword_argument="record", config=config, persistence_store=dynamodb)
154-
def record_handler(record):
154+
def record_handler(record: SQSRecord):
155155
return {"message": record["body"]}
156156

157157

158-
@sqs_batch_processor(record_handler=record_handler)
158+
@idempotent_function(data_keyword_argument="data", config=config, persistence_store=dynamodb)
159+
def dummy(arg_one, arg_two, data: dict, **kwargs):
160+
return {"data": data}
161+
162+
163+
@batch_processor(record_handler=record_handler, processor=processor)
159164
def lambda_handler(event, context):
160165
# `data` parameter must be called as a keyword argument to work
161166
dummy("hello", "universe", data="test")
162-
return {"statusCode": 200}
167+
return processor.response()
163168
```
164169

165-
=== "Example event"
170+
=== "Batch event"
166171

167172
```json hl_lines="4"
168173
{
@@ -193,6 +198,79 @@ When using `idempotent_function`, you must tell us which keyword parameter in yo
193198
}
194199
```
195200

201+
=== "dataclass_sample.py"
202+
203+
```python hl_lines="3-4 23 32"
204+
from dataclasses import dataclass
205+
206+
from aws_lambda_powertools.utilities.idempotency import (
207+
DynamoDBPersistenceLayer, IdempotencyConfig, idempotent_function)
208+
209+
dynamodb = DynamoDBPersistenceLayer(table_name="idem")
210+
config = IdempotencyConfig(
211+
event_key_jmespath="messageId", # see Choosing a payload subset section
212+
use_local_cache=True,
213+
)
214+
215+
@dataclass
216+
class OrderItem:
217+
sku: str
218+
description: str
219+
220+
@dataclass
221+
class Order:
222+
item: OrderItem
223+
order_id: int
224+
225+
226+
@idempotent_function(data_keyword_argument="order", config=config, persistence_store=dynamodb)
227+
def process_order(order: Order):
228+
return f"processed order {order.order_id}"
229+
230+
231+
order_item = OrderItem(sku="fake", description="sample")
232+
order = Order(item=order_item, order_id="fake-id")
233+
234+
# `order` parameter must be called as a keyword argument to work
235+
process_order(order=order)
236+
```
237+
238+
=== "parser_pydantic_sample.py"
239+
240+
```python hl_lines="1-2 22 31"
241+
from aws_lambda_powertools.utilities.idempotency import (
242+
DynamoDBPersistenceLayer, IdempotencyConfig, idempotent_function)
243+
from aws_lambda_powertools.utilities.parser import BaseModel
244+
245+
dynamodb = DynamoDBPersistenceLayer(table_name="idem")
246+
config = IdempotencyConfig(
247+
event_key_jmespath="messageId", # see Choosing a payload subset section
248+
use_local_cache=True,
249+
)
250+
251+
252+
class OrderItem(BaseModel):
253+
sku: str
254+
description: str
255+
256+
257+
class Order(BaseModel):
258+
item: OrderItem
259+
order_id: int
260+
261+
262+
@idempotent_function(data_keyword_argument="order", config=config, persistence_store=dynamodb)
263+
def process_order(order: Order):
264+
return f"processed order {order.order_id}"
265+
266+
267+
order_item = OrderItem(sku="fake", description="sample")
268+
order = Order(item=order_item, order_id="fake-id")
269+
270+
# `order` parameter must be called as a keyword argument to work
271+
process_order(order=order)
272+
```
273+
196274
### Choosing a payload subset for idempotency
197275

198276
!!! tip "Dealing with always changing payloads"
@@ -209,7 +287,7 @@ Imagine the function executes successfully, but the client never receives the re
209287
!!! warning "Idempotency for JSON payloads"
210288
The payload extracted by the `event_key_jmespath` is treated as a string by default, so will be sensitive to differences in whitespace even when the JSON payload itself is identical.
211289

212-
To alter this behaviour, we can use the [JMESPath built-in function](jmespath_functions.md#powertools_json-function) `powertools_json()` to treat the payload as a JSON object rather than a string.
290+
To alter this behaviour, we can use the [JMESPath built-in function](jmespath_functions.md#powertools_json-function) `powertools_json()` to treat the payload as a JSON object (dict) rather than a string.
213291

214292
=== "payment.py"
215293

0 commit comments

Comments
 (0)