Я написал кусок кода в лямбда-выражении для запроса базы данных большое количество раз. Чтобы ускорить процесс, я использую массив обещаний и ожидаю 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,