Firebase Cloud Function如何低成本实现10秒延迟传参调用
最低成本10秒延迟触发实现方案
不要在当前数据库触发的函数里用setTimeout做等待,这种写法会让函数实例在等待的10秒内全程保持运行,等待时间全部计入计费,完全是无效成本。
成本最低的实现方式是用延迟任务队列做触发,全程没有函数空跑开销:
- 首次匹配校验未命中结果时,当前函数只需要向任务队列投递一个延迟10秒执行的任务,把
gameid放在任务载荷里,投递完成后当前函数直接返回终止,不会产生任何等待时长的费用 - 单独配置一个任务触发的云函数,10秒到期后队列会自动触发该函数,拿到传入的
gameid后执行原有的deleteReference校验逻辑即可
这个方案的计费只覆盖两个函数实际执行业务逻辑的时长:首次匹配逻辑的运行时长通常只有几十到几百毫秒,延迟触发的校验逻辑也是到点才启动运行,没有任何空等的无效计费。而且你原有
deleteReference里的匹配状态判断逻辑完全不用改——就算10秒内已经匹配成功,延迟任务触发后校验到匹配完成,也不会执行删除操作,不需要额外做任务取消的逻辑。
改造后的参考代码如下:
// 原有匹配触发函数 exports.myFunction = functions.database.ref('/match/{gameid}/').onCreate(async (snapshot, context) => { const gameid = context.params.gameid; // 原有的首次匹配处理逻辑 // const matchResult = ..... if (matchResult == true) { return null; } else { // 向任务队列投递延迟10秒执行的任务,传入gameid const task = { httpRequest: { httpMethod: 'POST', url: process.env.DELETE_TASK_TRIGGER_URL, body: Buffer.from(JSON.stringify({gameid: gameid})).toString('base64'), headers: { 'Content-Type': 'application/json' } }, scheduleTime: { seconds: Date.now() / 1000 + 10 // 延迟10秒执行 } }; // 提交任务后直接返回,函数立刻终止,不等待 await tasksClient.createTask({parent: queuePath, task: task}); return null; } }); // 延迟任务触发的校验删除函数 exports.delayedDeleteCheck = functions.https.onRequest(async (req, res) => { const {gameid} = req.body; await deleteReference(gameid); res.status(200).send('ok'); }); // 原有的删除校验逻辑不用改动 async function deleteReference(gameid) { // 原有的匹配状态重新校验逻辑 // const matchResult = ..... if (matchResult == false) { await database.ref("/match/").child(gameid).remove(); } }
补充说明:
- 不要用定时轮询数据库的方案做这个需求,定时函数哪怕高频触发,长期运行的成本比单条延迟任务高很多,而且触发精度不够
- 不要用函数内sleep/setTimeout的方案,除了等待时长计费,函数实例还有可能在等待期被平台回收,导致10秒后的逻辑根本不执行,可靠性差
内容的提问来源于stack exchange,提问作者ursan526
相关产品推荐
相关产品推荐

