Skip to content
Merged
Prev Previous commit
Next Next commit
Improving doc
  • Loading branch information
leandrodamascena committed Apr 3, 2024
commit 5f50be5a63e14a6162d79f838c54973f9e68b5a7
16 changes: 14 additions & 2 deletions docs/utilities/idempotency.md
Original file line number Diff line number Diff line change
Expand Up @@ -950,20 +950,32 @@ You can set up a `response_hook` in the `IdempotentConfig` class to access the r

=== "Using an Idempotent Response Hook"

```python hl_lines="15 17 20 31"
```python hl_lines="18 20 23 32"
--8<-- "examples/idempotency/src/working_with_response_hook.py"
```

=== "Sample event"

```json
--8<-- "examples/idempotency/src/getting_started_with_idempotency_payload.json"
--8<-- "examples/idempotency/src/working_with_response_hook_payload.json"
```

???+ info "Info: Using custom de-serialization?"

The response_hook is called after the custom de-serialization so the payload you process will be the de-serialized version.

#### Being a good citizen

Using Response hooks can add subtle improvements to manipulating returned data from idempotent operations, but also add significant complexity if you're not careful.

Keep the following in mind when authoring hooks for Idempotency utility:

1. **Response hook works exclusively when operations are idempotent.** Carefully consider the logic within the `Response hook` and prevent any attempt to access the key from relying exclusively on idempotent operations.

2. **Catch your own exceptions.** Catch and handle known exceptions to your logic.

3. **Watch out when you are decorating the Lambda Handler and using the Response hook.** If you don't catch and handle exceptions in your `Response hook`, your function might not run properly.

## Compatibility with other utilities

### Batch
Expand Down
36 changes: 28 additions & 8 deletions examples/idempotency/src/working_with_response_hook.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
from datetime import datetime
import datetime
import uuid
from typing import Dict

from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.idempotency import (
DynamoDBPersistenceLayer,
IdempotencyConfig,
idempotent,
idempotent_function,
)
from aws_lambda_powertools.utilities.idempotency.persistence.base import (
DataRecord,
)
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = Logger()


def my_response_hook(response: Dict, idempotent_data: DataRecord) -> Dict:
# Return inserted Header data into the Idempotent Response
Expand All @@ -19,18 +23,34 @@ def my_response_hook(response: Dict, idempotent_data: DataRecord) -> Dict:
# expiry_timestamp could be None so include if set
expiry_timestamp = idempotent_data.expiry_timestamp
if expiry_timestamp:
expiry_time = datetime.fromtimestamp(int(expiry_timestamp))
expiry_time = datetime.datetime.fromtimestamp(int(expiry_timestamp))
response["x-idempotent-expiration"] = expiry_time.isoformat()

# Must return the response here
return response


persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")

dynamodb = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
config = IdempotencyConfig(response_hook=my_response_hook)


@idempotent(persistence_store=persistence_layer, config=config)
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return event
@idempotent_function(data_keyword_argument="order", config=config, persistence_store=dynamodb)
def process_order(order: dict) -> dict:
# create the order_id
order_id = str(uuid.uuid4())

# create your logic to save the order
# append the order_id created
order["order_id"] = order_id

# return the order
return {"order": order}


def lambda_handler(event: dict, context: LambdaContext):
config.register_lambda_context(context) # see Lambda timeouts section
try:
logger.info(f"Processing order id {event.get('order_id')}")
return process_order(order=event.get("order"))
except Exception as err:
return {"status_code": 400, "error": f"Erro processing {str(err)}"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"order" : {
"user_id": "xyz",
"product_id": "123456789",
"quantity": 2,
"value": 30
}
}