如果项目不存在则插入到 DynamoDB

Insert to DynamoDB if item doesn't exits

我正在使用 aws-rekognition 对流媒体视频设置出勤检查,当一个人被识别时,lambda 应该将其写入 DynamoDB。 insertDynamo() 单独运行良好(当我不将其作为函数调用时),但是当我将其放入函数中时,它不会写入 DynamoDB table。知道哪里做错了吗?

var AWS = require('aws-sdk');
var today = new Date();
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
var hour = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();

exports.handler = async (event, context) => {
    //console.log('Received event:', JSON.stringify(event, null, 2));


    event.Records.forEach((record) => {

            // Kinesis data is base64 encoded so decode here
            const load = new Buffer(record.kinesis.data, 'base64').toString('ascii');
            const payload = JSON.parse(load);
           if(payload.FaceSearchResponse != null)
           {
               payload.FaceSearchResponse.forEach((face) =>  {

                   if(face.MatchedFaces != null && 
                         Object.keys(face.MatchedFaces).length > 0)
                   {
                       var id = JSON.stringify(face.MatchedFaces[0].Face.ExternalImageId, null, 4);
                       //this is hard code it ---needs to split string from kinesis(id)
                       insertDynamo(date,hour,'0001');
                   }
                   else
                   {
                       //do nothing
                   }
               });
           }
        });
    return `Successfully processed ${event.Records.length} records.`;
};

var insertDynamo = function(date,hour,id){
    exports.handler = async (event,context) => {
    const documentClient = new AWS.DynamoDB.DocumentClient();
    let responseBody = "";
    let statusCode = 0;

    const params = {
        TableName: "users",
        Item:{
            badgeNumber: id,
            assistance:{
                date:date,
                hour:hour
            }
        },
        ConditionExpression: 'attribute_not_exists(badgenumber)'    
    };

    try {
        const data = await documentClient.put(params).promise();
        responseBody = JSON.stringify(data);
        statusCode = 201;
    } catch (err) {
        responseBody = `Unable to put product: ${err}`;
        statusCode = 403;
    }    

    const response = {
        statusCode: statusCode,
        headers: {
            "Content-Type": "application/json"
        },
        body:responseBody
    }
    return response
}
};

您的 lambda 函数将在调用后立即完成,因为您使用 .forEach 循环遍历所有记录。这意味着您所有插入 DynamoDB 的请求都将在他们完成他们的 yobs 之前被取消。

针对您的情况,我有 2 个解决方案:

  1. 等到 lambda 回调堆栈清除

    只需在您的 lambda 函数前面加上 "config" 行

       context.callbackWaitsForEmptyEventLoop = true;
    
  2. 使用旧式 for 循环而不是 forEach(推荐)。 forEach 使用回调方式来解决每个问题,然后它不会像我们预期的那样与 async/await 关键字一起工作。

var AWS = require('aws-sdk');
var today = new Date();
var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
var hour = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();

exports.handler = async (event, context) => {
  //console.log('Received event:', JSON.stringify(event, null, 2));

  for (const record of event.Records) { // for of instead of forEach
    const load = new Buffer(record.kinesis.data, 'base64').toString('ascii');
    const payload = JSON.parse(load);
    if (payload.FaceSearchResponse != null) {
      for (const face of payload.FaceSearchResponse) { // for of instead of forEach
        if (face.MatchedFaces != null &&
          Object.keys(face.MatchedFaces).length > 0) {
          var id = JSON.stringify(face.MatchedFaces[0].Face.ExternalImageId, null, 4);
          //this is hard code it ---needs to split string from kinesis(id)
          await insertDynamo(date, hour, '0001'); // wait until task finish then solve next item
        }
        else {
          //do nothing
        }
      }
    }
  }
  return `Successfully processed ${event.Records.length} records.`;
};

var insertDynamo = function (date, hour, id) {
  // What is this?????????
  // exports.handler = async (event, context) => {

  // }

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

  const params = {
    TableName: "users",
    Item: {
      badgeNumber: id,
      assistance: {
        date: date,
        hour: hour
      }
    },
    ConditionExpression: 'attribute_not_exists(badgenumber)'
  };

  return documentClient.put(params).promise(); // enough for us
};