0

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

我检查了PostConfirmation添加 DynamoDB 记录的 Cloudwatch 时间戳,PreTokenGeneration并检查了 DynamoDB 中的 createDate。时间戳看起来不错。例如:

  • PostConfirmation表示已添加记录的日志条目的时间戳为2020-08-24T17:51:06.463Z
  • 添加的记录 (createdAt)的DynamoDB createdAt表示该记录是在2020-08-24T17:51:06.377Z.
  • lambda " PostConfirmationEND RequestId: xxxxx" 的时间戳为2020-08-24T17:51:06.465-05:00
  • PreTokenGeneration lambda 从查询结果开始,2020-08-24T17:51:12.866Z2020-08-24T17:51:13.680Z查询结果中表示它没有找到任何记录。

有人可以帮助我或提示我为什么会发生这种情况和/或我该如何解决这个问题?先感谢您。

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

这是为保存操作记录的 RequestMapping

{
    "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"
}

为保存操作记录的 ResponseMapping

{
    "logType": "ResponseMapping",
    "path": [
        "createAccountMember"
    ],
    "fieldName": "createAccountMember",
    "resolverArn": "<redacted>",
    "requestId": "<redacted>",
    "context": {
        "arguments": {
            "input": {
                "id": "<redacted>",
                "userID": "<redacted>",
                "accountID": "<redacted>",
                "membershipStatus": "active",
                "groupsEnrolledIn": [
                    "<redacted>",
                    "<redacted>",
                    "<redacted>"
                ],
                "recordOwner": "<redacted>",
                "createdAt": "2020-08-25T05:11:10.917Z",
                "updatedAt": "2020-08-25T05:11:10.917Z",
                "__typename": "AccountMember"
            }
        },
        "result": {
            "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"
        },
        "stash": {},
        "outErrors": []
    },
    "fieldInError": false,
    "errors": [],
    "parentType": "Mutation",
    "graphQLAPIId": "<redacted>",
    "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

{
    "logType": "RequestMapping",
    "path": [
        "listAccountMembers"
    ],
    "fieldName": "listAccountMembers",
    "resolverArn": "<redacted>",
    "requestId": "<redacted>",
    "context": {
        "arguments": {
            "filter": {
                "userID": {
                    "eq": "<redacted>"
                }
            }
        },
        "stash": {},
        "outErrors": []
    },
    "fieldInError": false,
    "errors": [],
    "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\"}"
}

这是记录的 responseMapping。您可以看到结果是一个空数组 ( items:[]),即使之前已经添加了记录并且我们已经consistentRead=true为查询指定了该记录。

{
    "logType": "ResponseMapping",
    "path": [
        "listAccountMembers"
    ],
    "fieldName": "listAccountMembers",
    "resolverArn": "<redacted>",
    "requestId": "<redacted>",
    "context": {
        "arguments": {
            "filter": {
                "userID": {
                    "eq": "<redacted>"
                }
            }
        },
        "result": {
            "items": [],
            "nextToken": "<redacted>",
            "scannedCount": 100
        },
        "stash": {},
        "outErrors": []
    },
    "fieldInError": false,
    "errors": [],
    "parentType": "Query",
    "graphQLAPIId": "<redacted>",
    "transformedTemplate": "\n{\"items\":[],\"nextToken\":\"<redacted>",\"scannedCount\":100,\"startedAt\":null}\n"
}

我还能错过什么?

更新02

我找到了可能的原因。这是因为我不熟悉 DynamoDB 的工作方式。查询或扫描操作按键获取结果。在这种情况下,不涉及密钥,因此它会考虑到所有记录的限制。在我的情况下,它是 100,然后它应用过滤器。因此,如果添加的记录不在前 100 个结果中,除非我通过分页(不适合特定需要),否则它无法找到它。

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

4

2 回答 2

1

默认情况下, DynamoDB最终是一致的。

根据文件

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

如果您需要立即阅读刚刚编写的内容,您可以选择使用强一致性读取。这通常通过在您的 DynamoDB 调用中指定ConsistentReadto 来完成。true

于 2020-08-25T03:49:38.907 回答
0

我找到了根本原因。查询或扫描操作按键获取结果。在这种情况下,不涉及任何密钥,因此它会考虑考虑限制的所有记录,在我的情况下是 100,然后它应用过滤器。因此,如果添加的记录不在前 100 个结果中,除非我通过分页(不适合我的特定需要)才能找到它。我没有注意到这一点,因为我不熟悉 DynamoDB 的工作方式。但是感谢@noel-llevares,我进行了更深入的研究以找到解决方案。

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

于 2020-08-27T15:49:38.110 回答