我正在使用AWS Lambda函数(Node 4.3),该函数需要遍历DynamoDB表中的所有项并更新某些属性。
我遇到的问题是如何让Lambda等到所有DynamoDB操作完成。
var async = require('async');
var aws = require('aws-sdk');
var doc = new aws.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {
doc.scan({
TableName: 'Occupations_dev'
}, function (err, data) {
console.log(data.Items.length);
var funcs = [];
data.Items.forEach(function (item) {
funcs.push(function (cb) {
item.Popularity = 0;
doc.put({
TableName: 'Occupations_dev',
Item: item
}, function (err, data) {
if (err) {
console.log("ERROR: " + item.Name);
cb(err);
} else {
console.log('Finished put for ' + item.Id)
cb(null, item);
}
});
});
});
async.parallel(funcs, function (err, results) {
console.log('Finished');
if (err) {
context.fail(err);
} else {
callback(null, 'Finished');
}
});
});
};
我尝试使用async.parallel
等待所有db.put
个请求完成,但只要Lambda函数运行,它就会以Process exited before completing request
错误结束。
它会更新一些的DynamoDB项目,但绝对不是全部。
我在错误时添加了一些console.log
次调用,但我在日志中看到的唯一输出是:
START RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870 Version: $LATEST
2017-03-30T02:08:11.691Z b72fd7c6-14ed-11e7-a95a-c1185af4e870 1362
END RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870
REPORT RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870 Duration: 37165.80 ms Billed Duration: 37200 ms Memory Size: 128 MB Max Memory Used: 128 MB
RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870 Process exited before completing request
使Lambda函数等到完成所有操作的正确方法是什么? (这不是一个庞大的数据量,所以我不担心运行超过5分钟并超时。)
答案 0 :(得分:1)
消息“在完成请求之前退出进程”表示在调用context.done(或context.succeed等)之前退出Javascript函数。
以下是一些建议:
首先,尝试增加该功能的内存限制。这一行Memory Size: 128 MB Max Memory Used: 128 MB
可能表示内存不足,并且该进程在没有调用最后一个回调的情况下被杀死。
增加内存限制后,您可能会看到以下内容之一:
您的功能会超时。在这种情况下,您可能需要增加表的预配置容量(和/或lambda超时)
即使函数没有超时结束,您可能会看到并非处理完所有表记录。这是因为如果扫描项目的总数超过最大数据集大小限制1 MB,则扫描和查询操作可能不会返回所有表的行。扫描完成后,您应检查LastEvaluatedKey是否与数据一起返回。如果是,则应进行另一次扫描,将LastEvaluatedKey值作为ExclusiveStartKey参数
答案 1 :(得分:1)
async.parallel
函数调用是异步发生的,这可能会使DynamoDB多次同时更新,并在数据库级别引发“太多连接”错误
我建议使用async.series
之类的同步操作来执行数据库更新。 DynamoDB应该不会一个接一个地处理这些更新。