11import  datetime 
22import  logging 
3+ import  os 
34from  typing  import  Any , Dict , Optional 
45
56import  boto3 
67from  botocore .config  import  Config 
78
9+ from  aws_lambda_powertools .shared  import  constants 
810from  aws_lambda_powertools .utilities .idempotency  import  BasePersistenceLayer 
911from  aws_lambda_powertools .utilities .idempotency .exceptions  import  (
1012    IdempotencyItemAlreadyExistsError ,
@@ -20,6 +22,8 @@ def __init__(
2022        self ,
2123        table_name : str ,
2224        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 ,
2327        expiry_attr : str  =  "expiration" ,
2428        status_attr : str  =  "status" ,
2529        data_attr : str  =  "data" ,
@@ -35,7 +39,12 @@ def __init__(
3539        table_name: str 
3640            Name of the table to use for storing execution records 
3741        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 
3948        expiry_attr: str, optional 
4049            DynamoDB attribute name for expiry timestamp, by default "expiration" 
4150        status_attr: str, optional 
@@ -64,10 +73,14 @@ def __init__(
6473
6574        self ._boto_config  =  boto_config  or  Config ()
6675        self ._boto3_session  =  boto3_session  or  boto3 .session .Session ()
76+         if  sort_key_attr  ==  key_attr :
77+             raise  ValueError (f"key_attr [{ key_attr } { sort_key_attr }  )
6778
6879        self ._table  =  None 
6980        self .table_name  =  table_name 
7081        self .key_attr  =  key_attr 
82+         self .static_pk_value  =  static_pk_value 
83+         self .sort_key_attr  =  sort_key_attr 
7184        self .expiry_attr  =  expiry_attr 
7285        self .status_attr  =  status_attr 
7386        self .data_attr  =  data_attr 
@@ -93,6 +106,11 @@ def table(self, table):
93106        """ 
94107        self ._table  =  table 
95108
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+ 
96114    def  _item_to_data_record (self , item : Dict [str , Any ]) ->  DataRecord :
97115        """ 
98116        Translate raw item records from DynamoDB to DataRecord 
@@ -117,7 +135,7 @@ def _item_to_data_record(self, item: Dict[str, Any]) -> DataRecord:
117135        )
118136
119137    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 )
121139
122140        try :
123141            item  =  response ["Item" ]
@@ -127,7 +145,7 @@ def _get_record(self, idempotency_key) -> DataRecord:
127145
128146    def  _put_record (self , data_record : DataRecord ) ->  None :
129147        item  =  {
130-             self .key_attr :  data_record .idempotency_key ,
148+             ** self ._get_key ( data_record .idempotency_key ) ,
131149            self .expiry_attr : data_record .expiry_timestamp ,
132150            self .status_attr : data_record .status ,
133151        }
@@ -168,7 +186,7 @@ def _update_record(self, data_record: DataRecord):
168186            expression_attr_names ["#validation_key" ] =  self .validation_key_attr 
169187
170188        kwargs  =  {
171-             "Key" : { self .key_attr :  data_record .idempotency_key } ,
189+             "Key" : self ._get_key ( data_record .idempotency_key ) ,
172190            "UpdateExpression" : update_expression ,
173191            "ExpressionAttributeValues" : expression_attr_values ,
174192            "ExpressionAttributeNames" : expression_attr_names ,
@@ -178,4 +196,4 @@ def _update_record(self, data_record: DataRecord):
178196
179197    def  _delete_record (self , data_record : DataRecord ) ->  None :
180198        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