generated from amazon-archives/__template_MIT-0
-
Notifications
You must be signed in to change notification settings - Fork 470
Bug: Idempotency key in idempotent_function fails to serialize dates/UUIDs #8065
Copy link
Copy link
Labels
bugSomething isn't workingSomething isn't workingtriagePending triage from maintainersPending triage from maintainers
Description
Expected Behaviour
The @idempotent_function decorator should be able to serialize any idempotency keys which are Pydantic models containing dates or UUIDs (or more precisely, any type that can be serialized with model_dump(mode="json")).
Current Behaviour
aws_lambda_powertools.utilities.idempotency.exceptions.IdempotencyPersistenceLayerError: Failed to save in progress record to idempotency store - (Object of type UUID is not JSON serializable)
Code snippet
# src/idempotency_serialization/main.py
from uuid import UUID
from aws_lambda_powertools.utilities import idempotency
from pydantic import BaseModel
idempotency_config = idempotency.IdempotencyConfig()
idempotency_persistence_layer = idempotency.DynamoDBPersistenceLayer(
table_name="idempotency"
)
class IdempotencyKey(BaseModel):
req_id: UUID
def handle_request(req: IdempotencyKey) -> None:
return _impl(req=req)
@idempotency.idempotent_function(
data_keyword_argument="req",
config=idempotency_config,
persistence_store=idempotency_persistence_layer,
)
def _impl(req: IdempotencyKey) -> None:
pass
# tests/test_idempotency.py
from uuid import uuid4
import boto3
from moto import mock_aws
@mock_aws
def test_idempotency() -> None:
client = boto3.client("dynamodb")
client.create_table(
TableName="idempotency",
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}],
BillingMode="PAY_PER_REQUEST",
)
from idempotency_serialization.main import IdempotencyKey, handle_request
handle_request(IdempotencyKey(req_id=uuid4()))Possible Solution
The _prepare_data function in base.py should probably use .model_dump(mode="json") instead of leaving mode unset, which defaults to "python" and does not serialize UUIDs to strings.
def _prepare_data(data: Any) -> Any:
"""Prepare data for json serialization.
We will convert Python dataclasses, pydantic models or event source data classes to a dict,
otherwise return data as-is.
"""
# Convert from dataclasses
if hasattr(data, "__dataclass_fields__"):
import dataclasses
return dataclasses.asdict(data)
# Convert from Pydantic model
if callable(getattr(data, "model_dump", None)):
return data.model_dump()
# Convert from event source data class
if callable(getattr(data, "dict", None)):
return data.dict()
# Return raw event
return getattr(data, "raw_event", data)Steps to Reproduce
mkdir idempotency-serialization
cd idempotency-serialization
uv init --build-backend uv
uv add aws-lambda-powertools pydantic moto pytest
mkdir -p src/idempotency_serialization
mkdir -p tests
touch src/idempotency_serialization/main.py
touch tests/test_idempotency.py
Then copy the snippets above into src/idempotency_serialization/main.py and tests/test_idempotency.py, and run uv run pytest.
You should get this error:
FAILED tests/test_idempotency.py::test_idempotency - aws_lambda_powertools.utilities.idempotency.exceptions.IdempotencyPersistenceLayerError: Failed to save in progress record to idempotency store - (Object of type UUID is not JSON serializable)
Powertools for AWS Lambda (Python) version
latest
AWS Lambda function runtime
3.14
Packaging format used
PyPi
Debugging logs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingtriagePending triage from maintainersPending triage from maintainers
Type
Projects
Status
Triage