diff --git a/order-events/app/events/set_as_expired.py b/order-events/app/events/set_as_expired.py index 2be6fcb..4c6d0ef 100644 --- a/order-events/app/events/set_as_expired.py +++ b/order-events/app/events/set_as_expired.py @@ -20,6 +20,7 @@ order_layer = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client) @event_source(data_class=EventBridgeEvent) @logger.inject_lambda_context def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: + """Set the order status to `EXPIRED` 24 hours after it becomes overdue.""" new_image = event.detail['new_image'] now_ = now() diff --git a/order-events/app/events/stopgap/schedule_expired.py b/order-events/app/events/stopgap/schedule_expired.py new file mode 100644 index 0000000..44ab185 --- /dev/null +++ b/order-events/app/events/stopgap/schedule_expired.py @@ -0,0 +1,33 @@ +from datetime import timedelta + +from aws_lambda_powertools import Logger +from aws_lambda_powertools.utilities.data_classes import ( + EventBridgeEvent, + event_source, +) +from aws_lambda_powertools.utilities.typing import LambdaContext +from layercake.dateutils import fromisoformat, ttl +from layercake.dynamodb import ( + DynamoDBPersistenceLayer, +) + +from boto3clients import dynamodb_client +from config import ORDER_TABLE + +logger = Logger(__name__) +order_layer = DynamoDBPersistenceLayer(ORDER_TABLE, dynamodb_client) + + +@event_source(data_class=EventBridgeEvent) +@logger.inject_lambda_context +def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool: + new_image = event.detail['new_image'] + due_date = fromisoformat(new_image['due_date']) + + return order_layer.put_item( + item={ + 'id': new_image['id'], + 'sk': 'schedules#set_as_expired', + 'ttl': ttl(start_dt=due_date + timedelta(hours=24)), + } + ) diff --git a/order-events/template.yaml b/order-events/template.yaml index 3e06de2..5e70f19 100644 --- a/order-events/template.yaml +++ b/order-events/template.yaml @@ -158,6 +158,30 @@ Resources: new_image: sk: [schedules#set_as_expired] + EventScheduleExpiredFunction: + Type: AWS::Serverless::Function + Properties: + Handler: events.stopgap.schedule_expired.lambda_handler + LoggingConfig: + LogGroup: !Ref EventLog + Policies: + - DynamoDBWritePolicy: + TableName: !Ref OrderTable + Events: + Event: + Type: EventBridgeRule + Properties: + Pattern: + resources: [!Ref OrderTable] + detail-type: [INSERT] + detail: + new_image: + sk: ["0"] + status: [PENDING] + payment_method: [MANUAL] + due_date: + - exists: true + EventRemoveSlotsFunction: Type: AWS::Serverless::Function Properties: diff --git a/order-events/tests/events/stopgap/test_schedule_expired.py b/order-events/tests/events/stopgap/test_schedule_expired.py new file mode 100644 index 0000000..e8625cc --- /dev/null +++ b/order-events/tests/events/stopgap/test_schedule_expired.py @@ -0,0 +1,31 @@ +from decimal import Decimal + +from aws_lambda_powertools.utilities.typing import LambdaContext +from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair + +import events.stopgap.schedule_expired as app + + +def test_schedule_expired( + dynamodb_client, + dynamodb_persistence_layer: DynamoDBPersistenceLayer, + lambda_context: LambdaContext, +): + event = { + 'detail': { + 'new_image': { + 'id': '123', + 'sk': '0', + 'due_date': '2025-07-04T08:34:45.780000-03:00', + } + } + } + + assert app.lambda_handler(event, lambda_context) + assert { + 'sk': 'schedules#set_as_expired', + 'ttl': Decimal('1751715285'), + 'id': '123', + } == dynamodb_persistence_layer.get_item( + key=KeyPair('123', 'schedules#set_as_expired') + )