1
1
import datetime
2
2
import logging
3
+ import os
3
4
from typing import Any , Dict , Optional
4
5
5
6
import boto3
6
7
from botocore .config import Config
7
8
9
+ from aws_lambda_powertools .shared import constants
8
10
from aws_lambda_powertools .utilities .idempotency import BasePersistenceLayer
9
11
from aws_lambda_powertools .utilities .idempotency .exceptions import (
10
12
IdempotencyItemAlreadyExistsError ,
@@ -20,6 +22,8 @@ def __init__(
20
22
self ,
21
23
table_name : str ,
22
24
key_attr : str = "id" ,
25
+ static_pk_value : str = f"idempotency#{ os .getenv (constants .LAMBDA_FUNCTION_NAME_ENV , '' )} " ,
26
+ sort_key_attr : Optional [str ] = None ,
23
27
expiry_attr : str = "expiration" ,
24
28
status_attr : str = "status" ,
25
29
data_attr : str = "data" ,
@@ -35,7 +39,12 @@ def __init__(
35
39
table_name: str
36
40
Name of the table to use for storing execution records
37
41
key_attr: str, optional
38
- DynamoDB attribute name for key, by default "id"
42
+ DynamoDB attribute name for partition key, by default "id"
43
+ static_pk_value: str, optional
44
+ DynamoDB attribute value for partition key, by default "idempotency#<function-name>".
45
+ This will be used if the sort_key_attr is set.
46
+ sort_key_attr: str, optional
47
+ DynamoDB attribute name for the sort key
39
48
expiry_attr: str, optional
40
49
DynamoDB attribute name for expiry timestamp, by default "expiration"
41
50
status_attr: str, optional
@@ -64,10 +73,14 @@ def __init__(
64
73
65
74
self ._boto_config = boto_config or Config ()
66
75
self ._boto3_session = boto3_session or boto3 .session .Session ()
76
+ if sort_key_attr == key_attr :
77
+ raise ValueError (f"key_attr [{ key_attr } ] and sort_key_attr [{ sort_key_attr } ] cannot be the same!" )
67
78
68
79
self ._table = None
69
80
self .table_name = table_name
70
81
self .key_attr = key_attr
82
+ self .static_pk_value = static_pk_value
83
+ self .sort_key_attr = sort_key_attr
71
84
self .expiry_attr = expiry_attr
72
85
self .status_attr = status_attr
73
86
self .data_attr = data_attr
@@ -93,6 +106,11 @@ def table(self, table):
93
106
"""
94
107
self ._table = table
95
108
109
+ def _get_key (self , idempotency_key : str ) -> dict :
110
+ if self .sort_key_attr :
111
+ return {self .key_attr : self .static_pk_value , self .sort_key_attr : idempotency_key }
112
+ return {self .key_attr : idempotency_key }
113
+
96
114
def _item_to_data_record (self , item : Dict [str , Any ]) -> DataRecord :
97
115
"""
98
116
Translate raw item records from DynamoDB to DataRecord
@@ -117,7 +135,7 @@ def _item_to_data_record(self, item: Dict[str, Any]) -> DataRecord:
117
135
)
118
136
119
137
def _get_record (self , idempotency_key ) -> DataRecord :
120
- response = self .table .get_item (Key = { self .key_attr : idempotency_key } , ConsistentRead = True )
138
+ response = self .table .get_item (Key = self ._get_key ( idempotency_key ) , ConsistentRead = True )
121
139
122
140
try :
123
141
item = response ["Item" ]
@@ -127,7 +145,7 @@ def _get_record(self, idempotency_key) -> DataRecord:
127
145
128
146
def _put_record (self , data_record : DataRecord ) -> None :
129
147
item = {
130
- self .key_attr : data_record .idempotency_key ,
148
+ ** self ._get_key ( data_record .idempotency_key ) ,
131
149
self .expiry_attr : data_record .expiry_timestamp ,
132
150
self .status_attr : data_record .status ,
133
151
}
@@ -168,7 +186,7 @@ def _update_record(self, data_record: DataRecord):
168
186
expression_attr_names ["#validation_key" ] = self .validation_key_attr
169
187
170
188
kwargs = {
171
- "Key" : { self .key_attr : data_record .idempotency_key } ,
189
+ "Key" : self ._get_key ( data_record .idempotency_key ) ,
172
190
"UpdateExpression" : update_expression ,
173
191
"ExpressionAttributeValues" : expression_attr_values ,
174
192
"ExpressionAttributeNames" : expression_attr_names ,
@@ -178,4 +196,4 @@ def _update_record(self, data_record: DataRecord):
178
196
179
197
def _delete_record (self , data_record : DataRecord ) -> None :
180
198
logger .debug (f"Deleting record for idempotency key: { data_record .idempotency_key } " )
181
- self .table .delete_item (Key = { self .key_attr : data_record .idempotency_key } )
199
+ self .table .delete_item (Key = self ._get_key ( data_record .idempotency_key ) )
0 commit comments