Вставить в DynamoDB, если элемент не выходит - PullRequest
0 голосов
/ 08 октября 2019

Я настраиваю проверку посещаемости потокового видео с помощью aws-rekognition, когда человек идентифицируется, тогда лямбда должна записать его в DynamoDB. insertDynamo() отлично работает в одиночку (когда я не вызываю его как функцию), но когда я помещаю его в функцию, он не записывается в таблицу DynamoDB. Есть идеи, что я делаю не так?

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
}
};

1 Ответ

0 голосов
/ 09 октября 2019

Ваша лямбда-функция завершится сразу после вызова, потому что вы используете .forEach для циклического прохождения всех записей. Это означает, что все ваши запросы на вставку в DynamoDB будут отменены, прежде чем они завершат свою работу.

У меня есть 2 решения для вашего случая:

  1. Подождите, пока стек обратного вызова лямбды не будетclear

    Просто добавьте строку "config" к вашей лямбда-функции

       context.callbackWaitsForEmptyEventLoop = true;
    
  2. Используйте old school for loop вместо 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
};
...