使用 AWS Lambda 将记录推送到 AWS DynamoDB

Pushing records to AWS DynamoDB with AWS Lambda

我正在尝试将记录从 AWS Lambda 函数推送到 AWS DynamoDB。我可以使用 AWS API 从我的电脑成功推送一条记录,但是当我将代码部署到 AWS 时,我被卡住了。

下面是可以成功从我的 PC 推送记录的示例代码:

const AWS = require("aws-sdk");
AWS.config.update({
  region: "eu-west-1",
  endpoint: "https://dynamodb.eu-west-1.amazonaws.com"
});
const docClient = new AWS.DynamoDB.DocumentClient();

const params = {
  TableName: "hello-world-bot",
  Item: {
    timestamp: Date.now(),
    chat_id: 123,
    text: 'text',
  },
};

console.log("Adding a new item...");
docClient.put(params, function(err, data) {
    if (err) {
        console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
    } else {
        console.log("Added item:", JSON.stringify(data, null, 2));
    }
});

DynamoDB 中的结果: Screenshot from DynamoDB console

这是我要部署到 Lambda 的代码:

const AWS = require("aws-sdk");
AWS.config.update({
  region: "eu-west-1",
  endpoint: "https://dynamodb.eu-west-1.amazonaws.com",
});
const docClient = new AWS.DynamoDB.DocumentClient();

module.exports.helloworld = (event) => {
  const params = {
    TableName: "hello-world-bot",
    Item: {
      timestamp: Date.now(),
      chat_id: 123,
      text: "text",
    },
  };

  console.log("Adding a new item...");
  docClient.put(params, function (err, data) {
    if (err) {
      console.error(
        "Unable to add item. Error JSON:",
        JSON.stringify(err, null, 2)
      );
    } else {
      console.log("Added item:", JSON.stringify(data, null, 2));
    }
  });
  return { statusCode: 200 };
};

而且麻烦的是,当Lambda函数运行s时,DynamoDB中没有任何记录。 以下是当我拉取 Lambda 外部 API 并尝试 运行 函数时来自 CloudWatch 的日志:

START RequestId: d9e171c2-a763-4df1-9ec3-06d79eb68a1e Version: $LATEST
2021-08-13T06:03:01.974Z    d9e171c2-a763-4df1-9ec3-06d79eb68a1e    INFO    Adding a new item...
END RequestId: d9e171c2-a763-4df1-9ec3-06d79eb68a1e
REPORT RequestId: d9e171c2-a763-4df1-9ec3-06d79eb68a1e  Duration: 45.04 ms  Billed Duration: 46 ms  Memory Size: 1024 MB    Max Memory Used: 88 MB  Init Duration: 524.54 ms

如您所见,没有任何关于权限或其他方面的错误。 这些是其凭据在 Lambda 中与此函数一起使用的用户权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:BatchGetItem",
                "dynamodb:GetItem",
                "dynamodb:Query",
                "dynamodb:Scan",
                "dynamodb:BatchWriteItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem"
            ],
            "Resource": "arn:aws:dynamodb:eu-west-1:120400915578:table/hello-world-bot"
        }
    ]
}

您的 return { statusCode: 200 }; 结束了 lambda 调用,但它不会等待 put 请求完成。实际上,它可能甚至不等待它开始。

return 来自 put 回调的主函数,或者使用 promises。承诺示例:

module.exports.helloworld = async (event) => { // <- use async
  const params = {
    TableName: "hello-world-bot",
    Item: {
      timestamp: Date.now(),
      chat_id: 123,
      text: "text",
    },
  }

  console.log("Adding a new item...")
  // Create a promise and return it
  return docClient
    .put(params)
    .promise()
    .then(() => {
      console.log("success")
      return {statusCode: 200}
    })
    .catch(e => {
      console.log("error: ", e)
      return {statusCode: 500}
    })
}

此外,正如@jens 在评论中指出的那样,不需要明确设置 dynamodb 端点

正如我在其他答案的评论中指出的那样,他们的 return 陈述似乎并不完全正确。我更愿意对 lambda 和开箱即用的 AWS SDK 支持的承诺使用异步等待语法。

这会将您的代码更改为如下所示:

const AWS = require("aws-sdk");
const docClient = new AWS.DynamoDB.DocumentClient();

module.exports.helloworld = async (event) => {
  const params = {
    TableName: "hello-world-bot",
    Item: {
      timestamp: Date.now(),
      chat_id: 123,
      text: "text",
    },
  };

  console.log("Adding a new item...");
  try {
    await docClient.put(params).promise();
    return { statusCode: 200 };
  } catch (err) {
    console.error("Unable to add item. Error JSON:",
        JSON.stringify(err, null, 2));
    return { statusCode: 500 };
  }
};

PS:正如评论中所指出的,如果您使用的是默认端点,则无需为 DynamoDB 设置端点。因为你是 运行 作为 Lambda 的函数,AWS_REGION 环境变量将自动设置,所以你也不需要自己配置它(除非你想访问 DynamoDB table在另一个地区)。