Module aws_lambda_powertools.utilities.idempotency.idempotency
Primary interface for idempotent Lambda functions utility
Functions
def idempotent(handler: Callable[[Any, LambdaContext], Any],
event: dict[str, Any],
context: LambdaContext,
persistence_store: BasePersistenceLayer,
config: IdempotencyConfig | None = None,
key_prefix: str | None = None,
**kwargs) ‑> Any-
Expand source code
@lambda_handler_decorator def idempotent( handler: Callable[[Any, LambdaContext], Any], event: dict[str, Any], context: LambdaContext, persistence_store: BasePersistenceLayer, config: IdempotencyConfig | None = None, key_prefix: str | None = None, **kwargs, ) -> Any: """ Decorator to handle idempotency Parameters ---------- handler: Callable Lambda's handler event: dict Lambda's Event context: dict Lambda's Context persistence_store: BasePersistenceLayer Instance of BasePersistenceLayer to store data config: IdempotencyConfig Configuration key_prefix: str | Optional Custom prefix for idempotency key: key_prefix#hash Example -------- **Processes Lambda's event in an idempotent manner** from aws_lambda_powertools.utilities.idempotency import ( idempotent, DynamoDBPersistenceLayer, IdempotencyConfig ) idem_config=IdempotencyConfig(event_key_jmespath="body") persistence_layer = DynamoDBPersistenceLayer(table_name="idempotency_store") @idempotent(config=idem_config, persistence_store=persistence_layer) def handler(event, context): return {"StatusCode": 200} """ # Skip idempotency controls when POWERTOOLS_IDEMPOTENCY_DISABLED has a truthy value # Raises a warning if not running in development mode if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")): warnings.warn( message="Disabling idempotency is intended for development environments only " "and should not be used in production.", category=PowertoolsUserWarning, stacklevel=2, ) return handler(event, context, **kwargs) config = config or IdempotencyConfig() config.register_lambda_context(context) args = event, context idempotency_handler = IdempotencyHandler( function=handler, function_payload=event, config=config, persistence_store=persistence_store, key_prefix=key_prefix, function_args=args, function_kwargs=kwargs, ) return idempotency_handler.handle()
Decorator to handle idempotency
Parameters
handler
:Callable
- Lambda's handler
event
:dict
- Lambda's Event
context
:dict
- Lambda's Context
persistence_store
:BasePersistenceLayer
- Instance of BasePersistenceLayer to store data
config
:IdempotencyConfig
- Configuration
key_prefix
:str | Optional
- Custom prefix for idempotency key: key_prefix#hash
Example
Processes Lambda's event in an idempotent manner
from aws_lambda_powertools.utilities.idempotency import ( idempotent, DynamoDBPersistenceLayer, IdempotencyConfig ) idem_config=IdempotencyConfig(event_key_jmespath="body") persistence_layer = DynamoDBPersistenceLayer(table_name="idempotency_store") @idempotent(config=idem_config, persistence_store=persistence_layer) def handler(event, context): return {"StatusCode": 200}
def idempotent_function(function: AnyCallableT | None = None,
*,
data_keyword_argument: str,
persistence_store: BasePersistenceLayer,
config: IdempotencyConfig | None = None,
output_serializer: BaseIdempotencySerializer | type[BaseIdempotencyModelSerializer] | None = None,
key_prefix: str | None = None,
**kwargs: Any) ‑> Any-
Expand source code
def idempotent_function( function: AnyCallableT | None = None, *, data_keyword_argument: str, persistence_store: BasePersistenceLayer, config: IdempotencyConfig | None = None, output_serializer: BaseIdempotencySerializer | type[BaseIdempotencyModelSerializer] | None = None, key_prefix: str | None = None, **kwargs: Any, ) -> Any: """ Decorator to handle idempotency of any function Parameters ---------- function: Callable Function to be decorated data_keyword_argument: str Keyword parameter name in function's signature that we should hash as idempotency key, e.g. "order" persistence_store: BasePersistenceLayer Instance of BasePersistenceLayer to store data config: IdempotencyConfig Configuration output_serializer: BaseIdempotencySerializer | type[BaseIdempotencyModelSerializer] | None Serializer to transform the data to and from a dictionary. If not supplied, no serialization is done via the NoOpSerializer. In case a serializer of type inheriting BaseIdempotencyModelSerializer is given, the serializer is derived from the function return type. key_prefix: str | Optional Custom prefix for idempotency key: key_prefix#hash Example -------- **Processes an order in an idempotent manner** from aws_lambda_powertools.utilities.idempotency import ( idempotent_function, DynamoDBPersistenceLayer, IdempotencyConfig ) idem_config=IdempotencyConfig(event_key_jmespath="order_id") persistence_layer = DynamoDBPersistenceLayer(table_name="idempotency_store") @idempotent_function(data_keyword_argument="order", config=idem_config, persistence_store=persistence_layer) def process_order(customer_id: str, order: dict, **kwargs): return {"StatusCode": 200} """ if not function: return cast( AnyCallableT, functools.partial( idempotent_function, data_keyword_argument=data_keyword_argument, persistence_store=persistence_store, config=config, output_serializer=output_serializer, key_prefix=key_prefix, **kwargs, ), ) if isclass(output_serializer) and issubclass(output_serializer, BaseIdempotencyModelSerializer): # instantiate an instance of the serializer class output_serializer = output_serializer.instantiate(function.__annotations__.get("return", None)) config = config or IdempotencyConfig() @functools.wraps(function) def decorate(*args, **kwargs): # Skip idempotency controls when POWERTOOLS_IDEMPOTENCY_DISABLED has a truthy value # Raises a warning if not running in development mode if strtobool(os.getenv(constants.IDEMPOTENCY_DISABLED_ENV, "false")): warnings.warn( message="Disabling idempotency is intended for development environments only " "and should not be used in production.", category=PowertoolsUserWarning, stacklevel=2, ) return function(*args, **kwargs) if data_keyword_argument not in kwargs: raise RuntimeError( f"Unable to extract '{data_keyword_argument}' from keyword arguments." f" Ensure this exists in your function's signature as well as the caller used it as a keyword argument", ) payload = kwargs.get(data_keyword_argument) idempotency_handler = IdempotencyHandler( function=function, function_payload=payload, config=config, persistence_store=persistence_store, output_serializer=output_serializer, key_prefix=key_prefix, function_args=args, function_kwargs=kwargs, ) return idempotency_handler.handle() return cast(AnyCallableT, decorate)
Decorator to handle idempotency of any function
Parameters
function
:Callable
- Function to be decorated
data_keyword_argument
:str
- Keyword parameter name in function's signature that we should hash as idempotency key, e.g. "order"
persistence_store
:BasePersistenceLayer
- Instance of BasePersistenceLayer to store data
config
:IdempotencyConfig
- Configuration
output_serializer
:BaseIdempotencySerializer | type[BaseIdempotencyModelSerializer] | None
- Serializer to transform the data to and from a dictionary. If not supplied, no serialization is done via the NoOpSerializer. In case a serializer of type inheriting BaseIdempotencyModelSerializer is given, the serializer is derived from the function return type.
key_prefix
:str | Optional
- Custom prefix for idempotency key: key_prefix#hash
Example
Processes an order in an idempotent manner
from aws_lambda_powertools.utilities.idempotency import ( idempotent_function, DynamoDBPersistenceLayer, IdempotencyConfig ) idem_config=IdempotencyConfig(event_key_jmespath="order_id") persistence_layer = DynamoDBPersistenceLayer(table_name="idempotency_store") @idempotent_function(data_keyword_argument="order", config=idem_config, persistence_store=persistence_layer) def process_order(customer_id: str, order: dict, **kwargs): return {"StatusCode": 200}