我有一个每分钟运行一次的后台作业来更新文档。如果更新时间超过一分钟,我需要跳过下一个后台作业。同步此逻辑的最佳方式是什么?
我目前有
export const pickWinnerBackgroundJob = functions.pubsub.schedule('every 1 minutes').onRun(async (context) => {
const lock = await admin.firestore()
.collection(`lock`)
.doc(BG_JOB_LOCK_DOCUMENT_ID)
.get();
if (lock.exists && lock.data()?.locked == true) {
return;
}
await admin.firestore()
.collection(LOCK_COLLECTION_NAME)
.doc(BG_JOB_LOCK_DOCUMENT_ID)
.set({ locked: true })
var promises: Promise<any>;
// Add document update promises and execute job
return Promise.all(promises).then(() => {
return admin.firestore()
.collection(LOCK_COLLECTION_NAME)
.doc(BG_JOB_LOCK_DOCUMENT_ID)
.set({ locked: false })
});
});
这是一种有效的方法吗?
这种方法看起来很合理,但您必须注意竞争条件。由于你可能无法完全阻止它们,你必须选择一种最适合你需求的策略,所以:要么在发生争用时跳过一分钟太多,要么偶尔会并行运行两个实例。
或者,您可以将此Cloud函数的最大实例数设置为1,而不用在代码中担心。看起来Firebase包装器中的语法是:
functions.pubsub.schedule('every 1 minutes').runWith({ maxInstances: 1 }).onRun(async (context) => {
您还可以使用每个函数调用来将下一个函数调用安排在当前函数调用之后一分钟。不能那样跑得太远。(你确实需要确保它们继续运行,所以你可能还需要一只看门狗(