javascript - DynamoDb put 不会在 lambda 测试或 cron 中写入/保存到表,但在无服务器中有效
问题描述
我正在抓取一堆 API 并将数据保存到 dynamodb 表中。
serverless invoke local -f runAggregator
在本地运行时一切正常。
然而,在我设置了 cron 之后,我注意到东西没有被保存到 Dynamodb 表中。
这是我的功能:
module.exports.runAggregator = async (event) => {
await runModules({ saveJobs: true });
return {
statusCode: 200,
body: JSON.stringify(
{
message: "Aggregate",
input: event,
},
null,
2
),
};
};
和runModules
功能:
module.exports = async ({ saveJobs }) => {
if (saveJobs) {
const flushDb = await flushDynamoDbTable();
console.log("Flushing Database: Complete");
console.log(flushDb);
}
// pseudo code
const allJobs = myLongArrayOfJobsFromApis
const goodJobs = allJobs.filter((job) => {
if (job.category) {
if (!job.category.includes("Missing map for")) return job;
}
});
// This runs absolutely fine locally...
if (saveJobs) goodJobs.forEach(saveJob); // see below for function
const badJobs = allJobs.filter((job) => {
if (!job.category) return job; // no role found from API
if (job.category.includes("Missing map for")) return job;
});
console.log("Total Jobs", allJobs.length);
console.log("Good Jobs", goodJobs.length);
console.log("Malformed Jobs", badJobs.length);
return uniqBy(badJobs, "category");
};
保存作业功能
// saveJob.js
module.exports = (job) => {
validateJob(job);
dynamoDb
.put({
TableName: tableName,
Item: job,
})
.promise();
};
当我在 lambda 控制台中运行“测试”时,我很困惑为什么这在本地工作得很好。我只是在 cron 运行后才发现表是空的。
解决方案
saveJob
执行异步操作(ddb.put().promise()
),但您既不等待其完成也不返回承诺。
由于runModules
函数中的 forEach 也不会等待任何内容,因此函数在调用 dynamodb 之前完成(因为 promise 与同步代码的工作方式),并且在 lambda 执行后进程被终止。
在本地,您不是在运行 lambda,而是在运行类似的东西。存在细微的差异,函数完成后发生的事情就是这些差异之一。所以它可能在本地工作,但它不会在实际的 lambda 上工作。
您需要做的是确保等待您对 dynamodb 的呼叫。就像是:
// saveJob.js
module.exports = (job) => {
validateJob(job);
return dynamoDb
.put({
TableName: tableName,
Item: job,
})
.promise();
};
并在您的主要功能中:
...
if (saveJobs) await Promise.all(...goodJobs.map(job => saveJob(job)))
// or with a Promise lib such as bluebird:
if (saveJobs) await Promise.map(goodJobs, job => saveJob(job))
// (or Promise.each(...) if you need to make sure this happens in sequence and not in parallel)
注意:您可以/应该调用一次(或至少更少次)batchWriteItem操作,而不是多次调用 dynamodb.put,该操作可以在一次调用中写入多达 25 个项目,从而在此过程中节省相当多的延迟。
推荐阅读
- android - Androidx 项目无法识别使用 android.support.v7 的库类
- sql - 在一对多关系中插入命令
- javascript - JavaScript 返回未定义 - AWS Comprehend
- vue.js - Favicon 没有出现在 VueJS 中
- android - 为什么 Intent 的额外字符串变成了另一个?
- java - 在 Groovy 中发出 Java Lambda
- javascript - 不能在 VUEJS 中的异步函数之外使用关键字“等待”
- spring-boot - spring.jpa.hibernate.ddl-auto=none 问题
- r - 当第一个参数是字符时,为什么 `ave` 和 `table` 返回字符?
- c# - 对象引用未设置为 iTextSharp 中对象的实例 在 Stackify 中跟踪