为什么执行调用cognito lambda的开玩笑的测试会触发PostConfirmation然后PreTokenGeneration时出现随机错误?

问题描述

我有一个PostConfirmation lambda触发器,它通过 GraphQL (appsync https调用)将数据添加 DynamoDB ,然后在{{ 1}} lambda。 通过我的应用程序用户界面手动测试时,一切正常。 但是,通过Jest测试执行时,由于在DynamoDB中找不到假定的记录信息,我有50%以上的时间得到错误。 通过UI应用程序手动测试时不会发生此问题。仅当通过Jest测试执行时。

我检查了PretokenGeneration DynamoDB记录添加PostConfirmation的Cloudwatch时间戳,并检查了DynamoDB中的createDate。时间戳看起来还可以。 例如:

  • 表示记录已添加PretokenGeneration日志条目的时间戳记为PostConfirmation
  • 添加的记录(createdAt)的 DynamoDB 2020-08-24T17:51:06.463Z表示该记录是在createdAt上创建的。
  • 2020-08-24T17:51:06.377Z lambda“ END RequestId:xxxxx”的时间戳记为PostConfirmation
  • PretokenGeneration lambda从2020-08-24T17:51:06.465-05:00开始,在2020-08-24T17:51:12.866Z查询结果表明未找到任何记录。

有人可以帮助我或给我提示为什么会发生和/或如何解决此问题吗?预先谢谢你。

考虑到@ noel-llevares的回答,我修改了VTL模板,使其包含ConsistentRead = true,但问题仍然存在。

这里是保存操作记录的RequestMapping

2020-08-24T17:51:13.680Z

为保存操作记录的ResponseMapping

{
    "logType": "RequestMapping","path": [
        "createAccountMember"
    ],"fieldName": "createAccountMember","resolverArn": "arn:aws:appsync:xx-xxxx-x:111111111:apis/<redacted>/types/Mutation/resolvers/createAccountMember","requestId": "<redacted>","context": {
        "arguments": {
            "input": {
                "id": "<redacted>","userID": "<redacted>","accountID": "<redacted>","membershipStatus": "active","groupsEnrolledIn": [
                    <redacted>
                ],"recordOwner": "<redacted>","createdAt": "2020-08-25T05:11:10.917Z","updatedAt": "2020-08-25T05:11:10.917Z","__typename": "AccountMember"
            }
        },"stash": {},"outErrors": []
    },"fieldInError": false,"errors": [],"parentType": "Mutation","graphQLAPIId": "<redacted>","transformedTemplate": "\n\n\n\n\n\n\n\n{\n  \"version\": \"2018-05-29\",\n  \"operation\": \"PutItem\",\n  \"key\":  {\n  \"id\":   {\"S\":\"<redacted>\"}\n},\n  \"attributeValues\": {\"accountID\":{\"S\":\"<redacted>\"},\"createdAt\":{\"S\":\"2020-08-25T05:11:10.917Z\"},\"recordOwner\":{\"S\":\"<redacted>\"},\"__typename\":{\"S\":\"AccountMember\"},\"id\":{\"S\":\"<redacted>\"},\"membershipStatus\":{\"S\":\"active\"},\"userID\":{\"S\":\"<redacted>\"},\"groupsEnrolledIn\":{\"L\":[{\"S\":\"<redacted>\"},{\"S\":\"<redacted>\"},{\"S\":\"<redacted>\"}]},\"updatedAt\":{\"S\":\"2020-08-25T05:11:10.917Z\"}},\n  \"condition\": {\"expression\":\"attribute_not_exists(#id)\",\"expressionNames\":{\"#id\":\"id\"}}\n}\n"
}

这是为列表操作记录的请求映射。您可以看到{ "logType": "ResponseMapping","resolverArn": "<redacted>","groupsEnrolledIn": [ "<redacted>","<redacted>","<redacted>" ],"result": { "accountID": "<redacted>","__typename": "AccountMember","id": "<redacted>","groupsEnrolledIn": [ "<redacted>","<redacted>" ],"updatedAt": "2020-08-25T05:11:10.917Z" },"transformedTemplate": "{\"accountID\":\"<redacted>\",\"createdAt\":\"2020-08-25T05:11:10.917Z\",\"recordOwner\":\"<redacted>\",\"__typename\":\"AccountMember\",\"id\":\"<redacted>\",\"membershipStatus\":\"active\",\"userID\":\"<redacted>\",\"groupsEnrolledIn\":[\"<redacted>\",\"<redacted>\",\"<redacted>\"],\"updatedAt\":\"2020-08-25T05:11:10.917Z\"}\n" }

consistentRead=true

这是已记录的responseMapping。您可以看到结果是一个空数组({ "logType": "RequestMapping","path": [ "listAccountMembers" ],"fieldName": "listAccountMembers","context": { "arguments": { "filter": { "userID": { "eq": "<redacted>" } } },"parentType": "Query","graphQLAPIId": "<redacted>,"transformedTemplate": " \n{\"version\":\"2018-05-29\",\"limit\":100,\"consistentRead\":true,\"filter\":{\"expression\":\"(#userID = :userID_eq)\",\"expressionNames\":{\"#userID\":\"userID\"},\"expressionValues\":{\":userID_eq\":{\"S\":\"<redacted>\"}}},\"operation\":\"Scan\"}" } ),即使该记录是先前添加的,并且我们为查询指定了items:[]

consistentRead=true

我还能缺少什么?

UPDATE02

我找到了可能的原因。因为我对DynamoDB的工作方式还是陌生的。查询或扫描操作按键获取结果。在这种情况下,不涉及任何键,因此它将考虑限制的情况下获取所有记录。在我的情况下为100,然后应用过滤器。因此,如果添加的记录不在前100个结果中,那么除非我进行分页,否则找不到该记录(不利于Muy的特定需求)。

TL; DR :我将查询更改为使用@key指令,并将userID作为键字段,并且问题已经消失,因为que字段是GSI且我希望检索的记录数这样的分区远小于100的限制。完成取消之前所做的调整后,我会将此添加为答案的一部分。

解决方法

DynamoDB在默认情况下最终是

根据documentation

当您从DynamoDB表中读取数据时,响应可能无法反映最近完成的写操作的结果。响应中可能包含一些过时的数据。如果您在短时间内重复读取请求,则响应应返回最新数据。

如果需要立即阅读刚写的内容,则可以选择使用高度一致的读取。通常,这是通过在DynamoDB调用中将ConsistentRead设置为true来完成的。

,

我找到了根本原因。查询或扫描操作按键获取结果。在这种情况下,不涉及任何键,因此它将所有记录都考虑到了限制,在本例中为100,然后应用了过滤器。因此,如果添加的记录不在前100个结果中,那么除非我进行分页(否则无法满足我的特定需求),否则找不到该记录。我没有注意到这一点,因为我是DynamoDB的新手。但是,感谢@ noel-llevares,我进行了更深入的研究以找到解决方案。

解决方案是将查询更改为使用名称为“ byUsername”的@key伪指令,该伪指令以AccountMember作为键字段存在于userID类型中,并且问题已经解决了,因为que字段是GSI,我希望通过这种分区检索的记录数远远少于100个限制。