@@ -735,15 +735,16 @@ def test_default_no_raise_on_missing_idempotency_key(
735735 idempotency_config : IdempotencyConfig , persistence_store : DynamoDBPersistenceLayer , lambda_context
736736):
737737 # GIVEN a persistence_store with use_local_cache = False and event_key_jmespath = "body"
738- persistence_store .configure (idempotency_config )
738+ function_name = "foo"
739+ persistence_store .configure (idempotency_config , function_name )
739740 assert persistence_store .use_local_cache is False
740741 assert "body" in persistence_store .event_key_jmespath
741742
742743 # WHEN getting the hashed idempotency key for an event with no `body` key
743744 hashed_key = persistence_store ._get_hashed_idempotency_key ({})
744745
745746 # THEN return the hash of None
746- expected_value = "test-func#" + md5 (serialize (None ).encode ()).hexdigest ()
747+ expected_value = f "test-func. { function_name } #" + md5 (serialize (None ).encode ()).hexdigest ()
747748 assert expected_value == hashed_key
748749
749750
@@ -781,7 +782,7 @@ def test_jmespath_with_powertools_json(
781782 idempotency_config : IdempotencyConfig , persistence_store : DynamoDBPersistenceLayer , lambda_context
782783):
783784 # GIVEN an event_key_jmespath with powertools_json custom function
784- persistence_store .configure (idempotency_config )
785+ persistence_store .configure (idempotency_config , "handler" )
785786 sub_attr_value = "cognito_user"
786787 static_pk_value = "some_key"
787788 expected_value = [sub_attr_value , static_pk_value ]
@@ -794,14 +795,14 @@ def test_jmespath_with_powertools_json(
794795 result = persistence_store ._get_hashed_idempotency_key (api_gateway_proxy_event )
795796
796797 # THEN the hashed idempotency key should match the extracted values generated hash
797- assert result == "test-func#" + persistence_store ._generate_hash (expected_value )
798+ assert result == "test-func.handler #" + persistence_store ._generate_hash (expected_value )
798799
799800
800801@pytest .mark .parametrize ("config_with_jmespath_options" , ["powertools_json(data).payload" ], indirect = True )
801802def test_custom_jmespath_function_overrides_builtin_functions (
802803 config_with_jmespath_options : IdempotencyConfig , persistence_store : DynamoDBPersistenceLayer , lambda_context
803804):
804- # GIVEN an persistence store with a custom jmespath_options
805+ # GIVEN a persistence store with a custom jmespath_options
805806 # AND use a builtin powertools custom function
806807 persistence_store .configure (config_with_jmespath_options )
807808
@@ -871,7 +872,9 @@ def _delete_record(self, data_record: DataRecord) -> None:
871872def test_idempotent_lambda_event_source (lambda_context ):
872873 # Scenario to validate that we can use the event_source decorator before or after the idempotent decorator
873874 mock_event = load_event ("apiGatewayProxyV2Event.json" )
874- persistence_layer = MockPersistenceLayer ("test-func#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ())
875+ persistence_layer = MockPersistenceLayer (
876+ "test-func.lambda_handler#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ()
877+ )
875878 expected_result = {"message" : "Foo" }
876879
877880 # GIVEN an event_source decorator
@@ -891,7 +894,9 @@ def lambda_handler(event, _):
891894def test_idempotent_function ():
892895 # Scenario to validate we can use idempotent_function with any function
893896 mock_event = {"data" : "value" }
894- persistence_layer = MockPersistenceLayer ("test-func#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ())
897+ persistence_layer = MockPersistenceLayer (
898+ "test-func.record_handler#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ()
899+ )
895900 expected_result = {"message" : "Foo" }
896901
897902 @idempotent_function (persistence_store = persistence_layer , data_keyword_argument = "record" )
@@ -908,7 +913,9 @@ def test_idempotent_function_arbitrary_args_kwargs():
908913 # Scenario to validate we can use idempotent_function with a function
909914 # with an arbitrary number of args and kwargs
910915 mock_event = {"data" : "value" }
911- persistence_layer = MockPersistenceLayer ("test-func#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ())
916+ persistence_layer = MockPersistenceLayer (
917+ "test-func.record_handler#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ()
918+ )
912919 expected_result = {"message" : "Foo" }
913920
914921 @idempotent_function (persistence_store = persistence_layer , data_keyword_argument = "record" )
@@ -923,7 +930,9 @@ def record_handler(arg_one, arg_two, record, is_record):
923930
924931def test_idempotent_function_invalid_data_kwarg ():
925932 mock_event = {"data" : "value" }
926- persistence_layer = MockPersistenceLayer ("test-func#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ())
933+ persistence_layer = MockPersistenceLayer (
934+ "test-func.record_handler#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ()
935+ )
927936 expected_result = {"message" : "Foo" }
928937 keyword_argument = "payload"
929938
@@ -940,7 +949,9 @@ def record_handler(record):
940949
941950def test_idempotent_function_arg_instead_of_kwarg ():
942951 mock_event = {"data" : "value" }
943- persistence_layer = MockPersistenceLayer ("test-func#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ())
952+ persistence_layer = MockPersistenceLayer (
953+ "test-func.record_handler#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ()
954+ )
944955 expected_result = {"message" : "Foo" }
945956 keyword_argument = "record"
946957
@@ -958,13 +969,19 @@ def record_handler(record):
958969def test_idempotent_function_and_lambda_handler (lambda_context ):
959970 # Scenario to validate we can use both idempotent_function and idempotent decorators
960971 mock_event = {"data" : "value" }
961- persistence_layer = MockPersistenceLayer ("test-func#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ())
972+ persistence_layer = MockPersistenceLayer (
973+ "test-func.record_handler#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ()
974+ )
962975 expected_result = {"message" : "Foo" }
963976
964977 @idempotent_function (persistence_store = persistence_layer , data_keyword_argument = "record" )
965978 def record_handler (record ):
966979 return expected_result
967980
981+ persistence_layer = MockPersistenceLayer (
982+ "test-func.lambda_handler#" + hashlib .md5 (serialize (mock_event ).encode ()).hexdigest ()
983+ )
984+
968985 @idempotent (persistence_store = persistence_layer )
969986 def lambda_handler (event , _ ):
970987 return expected_result
@@ -986,7 +1003,9 @@ def test_idempotent_data_sorting():
9861003 data_two = {"more_data" : "more data 1" , "data" : "test message 1" }
9871004
9881005 # Assertion will happen in MockPersistenceLayer
989- persistence_layer = MockPersistenceLayer ("test-func#" + hashlib .md5 (json .dumps (data_one ).encode ()).hexdigest ())
1006+ persistence_layer = MockPersistenceLayer (
1007+ "test-func.dummy#" + hashlib .md5 (json .dumps (data_one ).encode ()).hexdigest ()
1008+ )
9901009
9911010 # GIVEN
9921011 @idempotent_function (data_keyword_argument = "payload" , persistence_store = persistence_layer )
@@ -1017,3 +1036,24 @@ def dummy_handler(event, context):
10171036 dummy_handler (mock_event , lambda_context )
10181037
10191038 assert len (persistence_store .table .method_calls ) == 0
1039+
1040+
1041+ @pytest .mark .parametrize ("idempotency_config" , [{"use_local_cache" : True }], indirect = True )
1042+ def test_idempotent_function_duplicates (
1043+ idempotency_config : IdempotencyConfig , persistence_store : DynamoDBPersistenceLayer
1044+ ):
1045+ # Scenario to validate the both methods are called
1046+ mock_event = {"data" : "value" }
1047+ persistence_store .table = MagicMock ()
1048+
1049+ @idempotent_function (data_keyword_argument = "data" , persistence_store = persistence_store , config = idempotency_config )
1050+ def one (data ):
1051+ return "one"
1052+
1053+ @idempotent_function (data_keyword_argument = "data" , persistence_store = persistence_store , config = idempotency_config )
1054+ def two (data ):
1055+ return "two"
1056+
1057+ assert one (data = mock_event ) == "one"
1058+ assert two (data = mock_event ) == "two"
1059+ assert len (persistence_store .table .method_calls ) == 4
0 commit comments