From b7507b1fb9537d9afae17b9e751e7d7963fc420b Mon Sep 17 00:00:00 2001 From: Sudhanshu Sali Date: Sun, 31 May 2026 16:47:05 -0400 Subject: [PATCH 1/2] Revert "fix(idempotency): resolve tech debt issues with falsy responses and Redis persistency (#8176)" This reverts commit 08c99219e000738c7be3e5b22338566dcb76b987. --- .../utilities/idempotency/base.py | 4 ++-- .../idempotency/persistence/redis.py | 4 ++-- .../idempotency/_redis/test_redis_layer.py | 19 ------------------- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/aws_lambda_powertools/utilities/idempotency/base.py b/aws_lambda_powertools/utilities/idempotency/base.py index bee109ef842..f6a3563c103 100644 --- a/aws_lambda_powertools/utilities/idempotency/base.py +++ b/aws_lambda_powertools/utilities/idempotency/base.py @@ -167,7 +167,7 @@ def _process_idempotency(self, is_replay: bool): # We give preference to ReturnValuesOnConditionCheckFailure because it is a faster and more cost-effective # way of retrieving the existing record after a failed conditional write operation. record = exc.old_data_record or self._get_idempotency_record() - if is_replay and record is not None and record.status == STATUS_CONSTANTS["INPROGRESS"]: + if is_replay and record is not None and record.status == "INPROGRESS": return self._get_function_response() # If a record is found, handle it for status if record: @@ -296,7 +296,7 @@ def _get_function_response(self): else: try: - serialized_response: dict = self.output_serializer.to_dict(response) if response is not None else None + serialized_response: dict = self.output_serializer.to_dict(response) if response else None self.persistence_store.save_success(data=self.data, result=serialized_response) except Exception as save_exception: raise IdempotencyPersistenceLayerError( diff --git a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py index 82a44e079de..f5969f7bc1e 100644 --- a/aws_lambda_powertools/utilities/idempotency/persistence/redis.py +++ b/aws_lambda_powertools/utilities/idempotency/persistence/redis.py @@ -335,8 +335,8 @@ def _item_to_data_record(self, idempotency_key: str, item: dict[str, Any]) -> Da idempotency_key=idempotency_key, status=item[self.status_attr], in_progress_expiry_timestamp=in_progress_expiry_timestamp, - response_data=item.get(self.data_attr, ""), - payload_hash=item.get(self.validation_key_attr, ""), + response_data=str(item.get(self.data_attr)), + payload_hash=str(item.get(self.validation_key_attr)), expiry_timestamp=item.get("expiration"), ) diff --git a/tests/functional/idempotency/_redis/test_redis_layer.py b/tests/functional/idempotency/_redis/test_redis_layer.py index 22c3b9a6d83..c2a0976b0ab 100644 --- a/tests/functional/idempotency/_redis/test_redis_layer.py +++ b/tests/functional/idempotency/_redis/test_redis_layer.py @@ -330,25 +330,6 @@ def test_item_to_datarecord_conversion(valid_record): assert record.in_progress_expiry_timestamp == item[layer.in_progress_expiry_attr] -def test_item_to_datarecord_conversion_missing_optional_attributes(persistence_store_standalone_redis): - """ - When data_attr or validation_key_attr is missing from Redis, - response_data and payload_hash should be empty string, not the string "None". - Regression test for: https://github.com/aws-powertools/powertools-lambda-python/issues/8090 - """ - idempotency_key = "test-func#abc123" - item = { - persistence_store_standalone_redis.status_attr: "COMPLETED", - persistence_store_standalone_redis.expiry_attr: 9999999999, - # data_attr and validation_key_attr intentionally absent - } - - record = persistence_store_standalone_redis._item_to_data_record(idempotency_key, item) - - assert record.response_data == "" - assert record.payload_hash == "" - - def test_idempotent_function_and_lambda_handler_redis_basic( persistence_store_standalone_redis: RedisCachePersistenceLayer, lambda_context, From e96d7a92e34057bc8cdcc28ee7ec13e11a5e75ae Mon Sep 17 00:00:00 2001 From: Sudhanshu Sali Date: Sun, 31 May 2026 23:59:17 -0400 Subject: [PATCH 2/2] Pin Shadow workflow to current v0 SHA --- .github/workflows/shadow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/shadow.yml b/.github/workflows/shadow.yml index af66d3027a8..dd8e3a97f6a 100644 --- a/.github/workflows/shadow.yml +++ b/.github/workflows/shadow.yml @@ -25,7 +25,7 @@ permissions: jobs: shadow: - uses: sudsali/shadow/.github/workflows/shadow-review.yml@cc9aea0bf5407458db5be1a238387ca1d03d162f # v0 + uses: sudsali/shadow/.github/workflows/shadow-review.yml@38f2dd08914b79a43a2eb0100a246ad5e664acfc # v0 with: pr_number: ${{ inputs.pr_number }} dry_run: ${{ inputs.dry_run && 'true' || 'false' }}