Bug: CachePersistenceLayer raises IdempotencyValidationError on retries with the same payload when payload_validation_jmespath is set

已關閉 適合新手
#8,655 5 則留言 0 個 reaction 已指派 1 人 在 GitHub 檢視

維護者通常 1 天內回覆

@thebadalov 已經在處理了。

開始於 2026年10月24日。

  • #8656 來自 @thebadalov —— 未關閉

評估

難度
2/5
預估耗時
1-3 小時
新手友好度
83/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
活躍
技術堆疊
python, redis
領域
backend, databases

研究方向

從 Redis 持久化層的 CachePersistenceLayer._update_record 開始,接著將其對應關係與 _put_in_progress_record 以及 DynamoDB 層的 _update_record 比較。在 test_idempotent_function_and_lambda_handler_redis_validation 旁新增一個回歸案例,使用相同的 payload 重試,並驗證會傳回已儲存的回應。當 payload 驗證雜湊在完成後仍保留,且重試成功時,即告完成。

由索引模型根據 Issue 內容生成。

描述

bug good first issue idempotency
Expected Behaviour

With CachePersistenceLayer (Redis/Valkey) and payload_validation_jmespath set, a retry with the same payload should return the stored response, the same way it does with DynamoDBPersistenceLayer.

Current Behaviour

The second call with the exact same payload raises IdempotencyValidationError: Payload does not match stored record for this event key.

_put_in_progress_record stores the payload hash under validation_key_attr, but _update_record overwrites the whole key with a new SET that only contains data, status and expiration. The hash is lost when the record moves to COMPLETED, so on the next call payload_hash is read back as "" and never matches.

DynamoDBPersistenceLayer._update_record writes the validation key when payload_validation_enabled is true, so only the Redis layer is affected.

Code snippet
from aws_lambda_powertools.utilities.idempotency import IdempotencyConfig, idempotent_function
from aws_lambda_powertools.utilities.idempotency.persistence.redis import CachePersistenceLayer


class InMemoryClient:
    """Minimal client with the get/set/delete calls the layer uses."""

    def __init__(self):
        self.store = {}

    def get(self, name):
        return self.store.get(name)

    def set(self, name, value, ex=0, nx=False):
        if nx and name in self.store:
            return None
        self.store[name] = value
        return True

    def delete(self, name):
        self.store.pop(name, None)


client = InMemoryClient()
persistence_layer = CachePersistenceLayer(client=client)
config = IdempotencyConfig(event_key_jmespath="order_id", payload_validation_jmespath="amount")


@idempotent_function(data_keyword_argument="order", persistence_store=persistence_layer, config=config)
def process_order(order):
    return {"order_id": order["order_id"]}


order = {"order_id": "o-1", "amount": 10}
print(process_order(order=order))  # {'order_id': 'o-1'}
print(list(client.store.values())[0])  # no "validation" field in the stored record
print(process_order(order=order))  # IdempotencyValidationError
Possible Solution

Add the validation key to the mapping in CachePersistenceLayer._update_record, like _put_in_progress_record already does:

if self.payload_validation_enabled:
    item["mapping"][self.validation_key_attr] = data_record.payload_hash

The existing test test_idempotent_function_and_lambda_handler_redis_validation only covers a different payload, so a test for a same-payload retry would catch this. I'm happy to send a PR.

Steps to Reproduce

Run the snippet above. No Redis server is needed, the in-memory client follows the same get/set/delete calls. The same happens with a real Redis or Valkey client.

Powertools for AWS Lambda (Python) version

latest (also on develop)

AWS Lambda function runtime

3.13

Packaging format used

PyPi

Debugging logs
aws_lambda_powertools.utilities.idempotency.exceptions.IdempotencyValidationError: Payload does not match stored record for this event key
主要語言
Python
星號
3.3k
分支
511
平均合併
3 天 13 小時
30 天內合併 PR
110

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

aws-powertools/powertools-lambda-python 的其他 Issue

查看 aws-powertools/powertools-lambda-python 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。