Skip to content

Commit c702532

Browse files
committed
fix(idempotency): sorting keys before hashing
1 parent 27e3930 commit c702532

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

Diff for: aws_lambda_powertools/utilities/idempotency/persistence/base.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def _generate_hash(self, data: Any) -> str:
223223
224224
"""
225225
data = getattr(data, "raw_event", data) # could be a data class depending on decorator order
226-
hashed_data = self.hash_function(json.dumps(data, cls=Encoder).encode())
226+
hashed_data = self.hash_function(json.dumps(data, cls=Encoder, sort_keys=True).encode())
227227
return hashed_data.hexdigest()
228228

229229
def _validate_payload(self, data: Dict[str, Any], data_record: DataRecord) -> None:
@@ -310,7 +310,7 @@ def save_success(self, data: Dict[str, Any], result: dict) -> None:
310310
result: dict
311311
The response from function
312312
"""
313-
response_data = json.dumps(result, cls=Encoder)
313+
response_data = json.dumps(result, cls=Encoder, sort_keys=True)
314314

315315
data_record = DataRecord(
316316
idempotency_key=self._get_hashed_idempotency_key(data=data),

Diff for: tests/functional/idempotency/test_idempotency.py

+17
Original file line numberDiff line numberDiff line change
@@ -976,3 +976,20 @@ def lambda_handler(event, _):
976976
# THEN we expect the function and lambda handler to execute successfully
977977
assert fn_result == expected_result
978978
assert handler_result == expected_result
979+
980+
981+
def test_idempotent_data_sorting():
982+
# Scenario to validate same data in different order hashes to the same idempotency key
983+
data_one = {"data": "test message 1", "more_data": "more data 1"}
984+
data_two = {"more_data": "more data 1", "data": "test message 1"}
985+
986+
# Assertion will happen in MockPersistenceLayer
987+
persistence_layer = MockPersistenceLayer("test-func#" + hashlib.md5(json.dumps(data_one).encode()).hexdigest())
988+
989+
# GIVEN
990+
@idempotent_function(data_keyword_argument="payload", persistence_store=persistence_layer)
991+
def dummy(payload):
992+
return {"message": "hello"}
993+
994+
# WHEN
995+
dummy(payload=data_two)

0 commit comments

Comments
 (0)