Skip to content

Commit 20795e5

Browse files
committed
makes notify-restaurant function idempotent
1 parent 222137c commit 20795e5

File tree

5 files changed

+31
-2
lines changed

5 files changed

+31
-2
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ Status: Week 3 in progress
2828
* allows users to register or sign in to the Cognito user pool, using SRP
2929
* uses the Cognito JWT token to send requests from the browser to `/restaurants/search`
3030

31+
* [Lambda Power Tools](https://docs.powertools.aws.dev/lambda/python/latest/) is used for logging, idempotency and
32+
event sourced event parsing.
33+
3134
* database: DynamoDB
3235

3336
* Tests:

cdk/app.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
construct_id=f"Event{feature_name}",
3333
service_name=service_name,
3434
maturity_level=maturity_level,
35+
idempotency_table=db_stack.idempotency_table,
3536
)
3637

3738
ApiStack(

cdk/db_stack.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,26 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
1313

1414
self.table = aws_dynamodb.Table(
1515
scope=self,
16-
id=f"restaurants",
16+
id="restaurants",
1717
partition_key=aws_dynamodb.Attribute(
1818
name="name",
1919
type=aws_dynamodb.AttributeType.STRING
2020
),
2121
billing_mode=aws_dynamodb.BillingMode.PAY_PER_REQUEST
2222
)
2323

24+
self.idempotency_table = aws_dynamodb.Table(
25+
scope=self,
26+
id="idempotency",
27+
partition_key=aws_dynamodb.Attribute(
28+
name="id",
29+
type=aws_dynamodb.AttributeType.STRING
30+
),
31+
# name of the attribute that stores the time-to-live value:
32+
time_to_live_attribute="exiration",
33+
billing_mode=aws_dynamodb.BillingMode.PAY_PER_REQUEST
34+
)
35+
2436
CfnOutput(
2537
scope=self,
2638
id="restaurants_table_name",

cdk/event_stack.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
aws_events,
44
aws_sns, aws_lambda_python_alpha, Duration, aws_lambda, aws_events_targets, CfnOutput
55
)
6+
from aws_cdk.aws_dynamodb import Table
67
from aws_cdk.aws_events import EventPattern
78
from constructs import Construct
89

@@ -16,6 +17,7 @@ def __init__(
1617

1718
service_name: str,
1819
maturity_level: str,
20+
idempotency_table: Table,
1921

2022
**kwargs) -> None:
2123
super().__init__(scope, construct_id, **kwargs)
@@ -42,11 +44,13 @@ def __init__(
4244
"POWERTOOLS_SERVICE_NAME": service_name,
4345
"MATURITY_LEVEL": maturity_level,
4446
"EVENT_BUS_NAME": self.event_bus.event_bus_name,
45-
"TOPIC_ARN": self.topic.topic_arn
47+
"TOPIC_ARN": self.topic.topic_arn,
48+
"IDEMPOTENCY_TABLE_NAME": idempotency_table.table_name
4649
}
4750
)
4851
self.event_bus.grant_put_events_to(notify_restaurant_fn)
4952
self.topic.grant_publish(notify_restaurant_fn)
53+
idempotency_table.grant_read_write_data(notify_restaurant_fn)
5054

5155
rule = aws_events.Rule(
5256
scope=self,

src/functions/notify_restaurant/notify_restaurant.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
import boto3
44
from aws_lambda_powertools.logging import Logger
55
from aws_lambda_powertools.utilities.data_classes import event_source, EventBridgeEvent
6+
from aws_lambda_powertools.utilities.idempotency import DynamoDBPersistenceLayer, idempotent, IdempotencyConfig
67

78
logger = Logger(log_uncaught_exceptions=True)
89

910
bus_name = os.getenv("EVENT_BUS_NAME")
1011
if not bus_name:
1112
raise ValueError("EVENT_BUS_NAME environment variable is not set")
1213

14+
idempotency_table = os.getenv("IDEMPOTENCY_TABLE_NAME")
15+
if not bus_name:
16+
raise ValueError("IDEMPOTENCY_TABLE_NAME environment variable is not set")
17+
1318
topic_ARN = os.getenv("TOPIC_ARN")
1419
if not bus_name:
1520
raise ValueError("TOPIC_ARN environment variable is not set")
@@ -18,6 +23,10 @@
1823
sns_client = boto3.client("sns")
1924

2025
@event_source(data_class=EventBridgeEvent)
26+
@idempotent(
27+
persistence_store=DynamoDBPersistenceLayer(table_name=idempotency_table),
28+
config=IdempotencyConfig(event_key_jmespath='detail.orderId')
29+
)
2130
def handler(event: EventBridgeEvent, context):
2231

2332
order = event.detail

0 commit comments

Comments
 (0)