Description
Expected Behaviour
When payload validation is enabled, the idempotency package should retrieve the item from dynamo and create an IdempotentRecord which includes the payload hash.
Current Behaviour
When payload validation is enabled, the idempotency package retrieves the item from dynamo but does not properly set the payload hash on the IdempotentRecord object. When the payload hash from the previous request is compared with the current payload hash, an error is thrown because the hash does not match the retrieved hash (set to undefined).
Code snippet
Configuration:
const config = new IdempotencyConfig({
hashFunction: 'md5',
useLocalCache: false,
expiresAfterSeconds: 3600,
throwOnNoIdempotencyKey: false,
payloadValidationJmesPath: 'body',
eventKeyJmesPath: 'headers.idempotency-key'
});
const persistenceStore = new DynamoDBPersistenceLayer({
tableName: 'idempotency_store',
keyAttr: 'key'
});
makeHandlerIdempotent({ config, persistenceStore });
Offending Code: DynamoDBPersistenceLayer->_getRecord()
https://github.com/awslabs/aws-lambda-powertools-typescript/blob/main/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts#L108
Code that triggers error:
https://github.com/awslabs/aws-lambda-powertools-typescript/blob/main/packages/idempotency/src/persistence/BasePersistenceLayer.ts#L112
Steps to Reproduce
- Use the configuration shown above
- Execute a POST request against the configuration with an unique idempotency key
- Verify that the dynmodb record was set and that the payload hash was set in on the item
- Repeat the request with the same idempotency key and the same body
- A validation error is thrown.
Possible Solution
Update the DynamoDBPersistenceLayer->_getRecord() to include the validation
attribute value when creating the IdempotentRecord object.
return new IdempotencyRecord({
idempotencyKey: item[this.keyAttr],
status: item[this.statusAttr],
expiryTimestamp: item[this.expiryAttr],
inProgressExpiryTimestamp: item[this.inProgressExpiryAttr],
responseData: item[this.dataAttr],
payloadHash: item[this.validationKeyAttr]
});
Also check to make sure all of the other possible properties are capable of being set.
NOTE: the above was not tested but based on line-by-line debugging.
Powertools for AWS Lambda (TypeScript) version
latest
AWS Lambda function runtime
18.x
Packaging format used
npm
Execution logs
Error: Payload does not match stored record for this event key
at DynamoDBPersistenceLayer.validatePayload (/workspaces/lambda/service/node_modules/@aws-lambda-powertools/idempotency/src/persistence/BasePersistenceLayer.ts:306:15)
at DynamoDBPersistenceLayer.getRecord (/workspaces/lambda/service/node_modules/@aws-lambda-powertools/idempotency/src/persistence/BasePersistenceLayer.ts:104:10)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at before (/workspaces/lambda/service/node_modules/@aws-lambda-powertools/idempotency/src/middleware/makeHandlerIdempotent.ts:83:11)
at runMiddlewares (/workspaces/lambda/service/node_modules/@middy/core/index.cjs:159:21)
at runRequest (/workspaces/lambda/service/node_modules/@middy/core/index.cjs:119:9)
at Object.perform (/workspaces/lambda/service/src/utils/performerWrapper.js:28:22)
at Object.<anonymous> (/workspaces/lambda/service/test/integration/createTransfer.spec.js:95:38) {stack: 'Error: Payload does not match stored record f…est/integration/createTransfer.spec.js:95:38)', message: 'Payload does not match stored record for this event key'}