Lambda 函数处理程序执行 DynamoDB 更新两次

Lambda function handler executing DynamoDB update twice

提问人:b_a9f 提问时间:11/10/2022 最后编辑:Ermiya Eskandaryb_a9f 更新时间:11/11/2022 访问量:185

问:

我的 Lambda 函数应该增加 dynamodb 表中的值,我使用 .update API 作为原子计数器。 该值递增两次!我尝试更改增量变量值,它总是递增两次。 例如:我的 DynamoDB 表中的值是 2,增量值是 1。我测试了 Lambda 函数,dynamoDB 值为 4(而不是 3)。

相同的代码(没有处理程序函数)在 Lambda 外部成功运行(使用 JS SDK 从 VSCode 执行) 可能是什么问题?

'use strict';

const AWS = require("aws-sdk");
AWS.config.update({ region: "me-central-1" });

const docClient = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event) => {
await docClient.update(
  {
    TableName: "visitor-counter-table",
    Key: {
      "visitor-counter": "counter",
    },
    UpdateExpression: "set #num = #num + :incr",
    ExpressionAttributeNames: {
      "#num": "number",
    },
    ExpressionAttributeValues: {
      ":incr": 1,
    },
  },
  (err, data) => {
    err ? console.log(err) : console.log(data);
  }
).promise();

  return {"statusCode": 200, "body": "number added to DDB Success"}
};

这是我在 VSCode 上运行的代码:

const AWS = require("aws-sdk");
AWS.config.update({ region: "me-central-1" });

const docClient = new AWS.DynamoDB.DocumentClient();

docClient.update(
  {
    TableName: "visitor-counter-tbl",
    Key: {
      "visitor-counter": "counter",
    },
    UpdateExpression: "set #num = #num + :incr",
    ExpressionAttributeNames: {
      "#num": "number",
    },
    ExpressionAttributeValues: {
      ":incr": 1,
    },
  },
  (err, data) => {
    err ? console.log(err) : console.log(data);
  }
);
JavaScript 节点 .js 网络服务 AWS-Lambda 亚马逊 DynamoDB

评论

0赞 Ermiya Eskandary 11/11/2022
您能否准确显示您在本地运行的代码(即没有处理程序函数)?
0赞 b_a9f 11/11/2022
^ 完成,更新了问题@ErmiyaEskandary
0赞 Borislav Stoilov 11/11/2022
你如何触发 lambda?
0赞 b_a9f 11/11/2022
@BorislavStoilov为此,我在 lambda 中使用 TEST 按钮,但我也使用 API Gateway URL 触发它,这会产生相同的结果。
3赞 Ermiya Eskandary 11/11/2022
@b_a9f 这是因为您正在等待承诺,并同时使用回调 - 这是 2 倍。您应该等待 promise 或使用回调,而不是等待 promise 并使用回调。我很快就会输入答案:)很高兴它奏效了。

答:

1赞 Ermiya Eskandary 11/11/2022 #1

您将成功和失败回调传递给您,同时获取并等待生成的 promise。docClient.update

这意味着您最终会触发两次更新。

本地调用之所以有效,是因为您只是传递回调,而不是请求 promise () 然后等待它。这会导致触发一次更新。.promise()

要么使用 await,要么使用回调 - 不要两者兼而有之

这应该有效:

await docClient.update(
  {
    TableName: "visitor-counter-table",
    Key: {
      "visitor-counter": "counter",
    },
    UpdateExpression: "set #num = #num + :incr",
    ExpressionAttributeNames: {
      "#num": "number",
    },
    ExpressionAttributeValues: {
      ":incr": 1,
    },
  }
).promise();

评论

1赞 jarmod 11/11/2022
这很有趣。我想知道为什么会这样。为什么同时提供回调函数和请求 promise 会导致 2 倍的 API 请求?这似乎是 AWS 开发工具包中的一个错误,或者至少是一个非常可疑的结果,如果可能的话,值得预防。我几乎可以理解 1x API 请求的两个完成(一个是已履行的承诺,另一个是回调),但不能理解 2x API 请求。可能需要深入研究此处的代码才能了解更多信息。
1赞 jarmod 11/11/2022
好的,调用 将返回一个 AWSRequest 对象,您必须调用该对象才能实际发送 API 请求。但是调用实际执行,因此回调函数的存在会发送 API 请求。现在,该方法的代码“发送请求并返回一个 promise”,因此它也发送了请求。这就是为什么如果 callback 和 promise() 都存在,API 调用会发生两次。service.action(params).send()service.action(params, callback)if (callback) request.send(callback).promise()