Очень большой массив Promise all, показывающий периодический c сбой, вызванный из Lambda - PullRequest
0 голосов
/ 29 марта 2020

Я написал кусок кода в лямбда-выражении для запроса базы данных большое количество раз. Чтобы ускорить процесс, я использую массив обещаний и ожидаю Promise.all (обещания) ... Дело в том, что, похоже, я испытываю случайную ошибку, выдвигающую обещания в массив. Это не повторяется, что делает его похожим на проблему выделения ресурсов в AWS ... Но я изменил выделение DynamoDB на «По требованию», чтобы учесть это. Но из более чем 1000 обещаний около 10, похоже, не справляются. Когда я делаю около 12 000 обещаний в моем массиве, примерно 1%, похоже, не справляются. Который является гигантской болью.

Мой код выглядит следующим образом:

let month_index = 0;

console.log('promises[] = ' + scanResults.length + ' devices x ' + monthsToReport + ' months = ' + scanResults.length * monthsToReport + 'promises!');

do {
  var monStart = new Date(year, (month-1)); // July 2019.
  var ts_monStart = Math.round((monStart).getTime() / 1000);

  if (month === 11) {
    month = 0;
    year++
  } else {
    month++;
  }

  var monEnd   = new Date(year, (month-1));
  var ts_monEnd   = Math.round((monEnd).getTime() / 1000);

  console.log("start month = " + ts_monStart + ", end month = " + ts_monEnd);


  // Fill up Array of Promises: one for each devices data. the do / while loop repeats for each month.


  var promises = [];

  //     for (let i = 0; i < 500; i++) {
  for (let i = 0; i < scanResults.length; i++) {
    // console.log('i = ', i);

    try {
      // Define the Query Params.
      var dataParams = {
        ExpressionAttributeValues: {
          ":dynamoId": {S: scanResults[i].deviceId},
          ":f" : {N: ts_monStart.toString()},   // fromTime
          ":t" : {N: ts_monEnd.toString()}      // toTime
        },
        KeyConditionExpression: "id = :dynamoId and ts between :f AND :t",
        TableName: "SensorNodeData"
      };

      let month_index_d = month_index; // need let within scope for promises to resolve properly. Don't ask me why?! I don't care.

      // Add a promise to promise array! Callback grabs Count.

      if(scanResults[i].deviceId == "seq" ) {
        console.log('balls! ignoring this one.' +  scanResults[i]);
        scanResults[i].month[month_index_d] = 0;
        continue;
      }



      promises.push(dynamodb.query(dataParams, function(err, data) {
        if (err) {
          console.log("Error Pushing Promise: ", err);
          //        console.log('i = ' + i + ', device = ' + JSON.stringify(scanResults[i]) + ', params = ' + JSON.stringify(dataParams));
        } else {
          scanResults[i].month[month_index_d] = data.Count;
          //             console.log('Device ' + i + ' (' + scanResults[i].deviceId + ')' + ', month_index = ' + month_index_d + ', Count = ' + scanResults[i].month[month_index_d]);
        }
      }).promise());
    } catch(err) {
      console.log('promise ballsed up: ', err);
    }
  }

  // Using promise.all has reduced execution time by factor of how many devices * months! *much* faster.
  try {
    await Promise.all(promises).then( () => {
      console.log('Promises Done!');
    });
  } catch (err) {
    console.log('promise all ballsed up: ', err);
  }


  month_index++;

} while (monEnd < ts_today);

Однако в Cloudwatch я вижу следующую проблему примерно в 1% случаев, и не всегда для одних и тех же обещаний. Очень странный и самый раздражающий! Я довольно труби sh в узле, так что, возможно, я сделал что-то очень неправильное. Если это так, представьте, что вы объясняете ошибку очень глупому человеку. Это принесет максимум пользы для всех участников (особенно для меня).

INFO    Error Pushing Promise:  { TypeError: Cannot read property 'push' of undefined
    at Request.HTTP_DATA (/var/runtime/node_modules/aws-sdk/lib/event_listeners.js:389:35)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)
    at IncomingMessage.onReadable (/var/runtime/node_modules/aws-sdk/lib/event_listeners.js:289:32)
    at IncomingMessage.emit (events.js:198:13)
    at IncomingMessage.EventEmitter.emit (domain.js:448:20)
    at emitReadable_ (_stream_readable.js:555:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  message: 'Cannot read property \'push\' of undefined',
  code: 'TypeError',
  time: 2020-03-29T03:27:28.866Z,

1 Ответ

1 голос
/ 29 марта 2020

Если вы посмотрите на код, где обнаружена ошибка (node_modules/aws-sdk/lib/event_listeners.js:389:35), вы увидите, что это происходит, когда библиотека пытается прочитать данные из HTTP-соединения (предположительно в DynamoDB):

379     add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) {
380       if (chunk) {
381         if (AWS.util.isNode()) {
382           resp.httpResponse.numBytes += chunk.length;
383 
384           var total = resp.httpResponse.headers['content-length'];
385           var progress = { loaded: resp.httpResponse.numBytes, total: total };
386           resp.request.emit('httpDownloadProgress', [progress, resp]);
387         }
388 
389         resp.httpResponse.buffers.push(AWS.util.buffer.toBuffer(chunk)); <=== HERE
390       }
391     });

Упомянутый push - это попытка pu sh на resp.httpResponse.buffers, а не на ваш массив promises, как вы могли подумать.

Мне кажется, что создание ~ 12000 одновременных подключений к DynamoDB приводят к обрыву некоторых из них. Вы упомянули, что вы обновили распределение DynamoDB по требованию, что в конечном итоге решит эту проблему, но возможно, что это внезапное требование застигнет врасплох автоматическое масштабирование.

Я не знаю достаточно о DynamoDB говорит о специфике, но если вы хотите устранить неполадки, вы можете временно выделить ресурсы DynamoDB немного выше пикового автоматического выделения ресурсов c и попробовать тот же запрос. Если количество неудачных запросов уменьшается, то это может быть вероятным виновником.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...