-
Notifications
You must be signed in to change notification settings - Fork 153
Bug: idempotency utility throws IdempotencyPersistenceLayerError - Failed to update success record to idempotency store #2944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for opening your first issue here! We'll come back to you as soon as we can. |
To add some more info, I added in some logging:
Result to be saved:
And then I think the DB util client errors with the following:
|
Hi @cbarlow1993, thanks for the info - could you please share an example of what your lambda handler returns? The error message seems to suggest you might be returning a class instance, which the SDK doesn't know how to serialize. |
Yes, you are right. There is a class used format the response. If I just return a standard JSON payload, it does work correctly. Is there a way to support class responses?
|
Hi @cbarlow1993, thanks for confirming - that's most definitely the issue. Technically speaking the underlying AWS SDK function we are using to serialize values before writing them to DynamoDB can support this type of conversion by enabling the When the For example, having this class: class MyClass {
public foo: string;
public bar: string;
constructor(props: { foo: string; bar: string }) {
this.foo = props.foo;
this.bar = props.bar;
}
public greet() {
console.log(`hello ${this.foo}`);
}
} it would do this: import { marshall } from '@aws-sdk/util-dynamodb';
const instance = new MyClass({ foo: 'foo', bar: 'bar' });
const marshalled = marshall(
{ id: 'abcd', value: instance },
{ convertClassInstanceToMap: true }
);
// { id: { S: 'abcd' }, value: { M: { foo: { S: 'foo' }, bar: { S: 'bar' } } } } This would make sure the write operation is successful, which is nice, however it would break the idempotency further down the line. The issue with this conversion is that it's a one-way lossy conversion, meaning that it's not possible to rehydrate or otherwise reconstruct the class instance from the map record stored in DynamoDB. Building on top of the previous example, suppose we queried the value and unmarshalled it (aka convert it back from DynamoDB attribute to native JavaScript objects), the result would be this: import { unmarshall } from '@aws-sdk/util-dynamodb';
const restored = unmarshall({ id: { S: 'abcd' }, value: { M: { foo: { S: 'foo' }, bar: { S: 'bar' } } } });
// { id: 'abcd', value: { foo: 'foo', bar: 'bar' } } As you can see the restored item is now a plain object and no longer an instance of the original class. This is because we have lost any information about the class when serializing it. For this project specifically, I think this would be an undesirable behavior since the one of the key features of the Idempotency utility is to:
If we allowed class instances to be serialized, we would break this contract since we wouldn't be able to return the same stored payload on subsequent idempotent invocations/requests. This is also a known limitation of the utility that is called out in the docs (although it could perhaps be called out more prominently): Now, back to your use case, I don't think this is what you'd want either. I don't know what your If that's the case, if possible, I'd like to learn more about how/when this serialization happens so we can try to find a solution for your use case that would allow you to continue using our feature. Either way I think we'll have to make some changes to support this use case, so far I think allowing you to pass your own serializer function similar to how the Python implementation of Powertools for AWS does, and/or supporting response hooks (#2887) would probably help you. |
This issue has not received a response in 2 weeks. If you still think there is a problem, please leave a comment to avoid the issue from automatically closing. |
Greetings! We are closing this issue because it has been open a long time and hasn’t been updated in a while and may not be getting the attention it deserves. We encourage you to check if this is still an issue in the latest release and if you find that this is still a problem, please feel free to comment or reopen the issue. |
Expected Behavior
Successful idempotency write of successful request.
Current Behavior
After a successful write to the DynamoDB table for the idempotency record, once the handler has successfully executed with no errors thrown, it then throws the below error as the last log line of the execution.
It does successfully run the DeleteItemCommand hust before throwing this error and have verified with setting the dynamoDB client with a logger.
Code snippet
I'm using a HTTP V2 lambda event, expecting to use an idempotency key of the header of
header."idempotency-key"
. This seems to work.Steps to Reproduce
Use code snippet above
Possible Solution
Tried many different variations of the config and implementation and continuously the same error.
Powertools for AWS Lambda (TypeScript) version
latest
AWS Lambda function runtime
20.x
Packaging format used
npm
Execution logs
My code continues to execute and is successfully returning a HTTP V2 response of { statusCode: 200, JSON.stringify({ result: true}) }
The text was updated successfully, but these errors were encountered: