Cloud Function作为HTTP函数正常,定时调用失效问题排查
我有一个每日定时执行的Cloud Function如下:
export const dailyExecutedFunction = async (): Promise<void> => { try { // 其他代码 setRoutineAnalytics(); } catch (error) { functions.logger.error(error); functions.logger.error( 'Something went wrong with daily executed function', { structuredData: true } ); } };
对应的setRoutineAnalytics函数代码如下:
export async function setRoutineAnalytics(): Promise<void> { try { functions.logger.info('A'); const date = getDateFromDaysAgo(1); const dailyRoutines = await firestore .collection('today_routines') .where('date', '==', date) .get(); // 约300-400条文档 functions.logger.info('B'); // 更新routine analytics的其他代码 } catch (error) { functions.logger.error(error); functions.logger.error( 'Something went wrong with setting routine analytics', { structuredData: true } ); } }
已验证通过HTTP Cloud Function(functions.https.onRequest)手动调用setRoutineAnalytics时功能正常,但通过定时Pub/Sub Cloud Function(functions.pubsub)调用时却失效。查看日志发现仅输出了日志'A',没有输出'B',也无任何错误日志。请问可能是什么原因?
核心原因:未等待异步函数完成
在dailyExecutedFunction中调用setRoutineAnalytics()时没有添加await关键字。由于setRoutineAnalytics是异步函数,调用后会立即返回一个Promise,而定时函数没有等待这个Promise完成就结束了主逻辑。Cloud Functions的Pub/Sub触发类型会在函数主逻辑执行完毕后立即终止进程,不会等待未被
await的异步操作完成。这就导致setRoutineAnalytics中await firestore.get()的请求还未完成,函数就被强制终止,因此日志'B'无法输出,进程终止也会导致catch块无法捕获错误。而HTTP触发的函数生命周期相对宽松,可能会预留时间让未处理的异步操作完成,所以手动调用时功能正常。
解决方案:在调用
setRoutineAnalytics()时添加await,确保函数等待异步操作完成:export const dailyExecutedFunction = async (): Promise<void> => { try { // 其他代码 await setRoutineAnalytics(); // 添加await关键字 } catch (error) { functions.logger.error(error); functions.logger.error( 'Something went wrong with daily executed function', { structuredData: true } ); } };其他次要排查方向
- 检查Pub/Sub触发函数的权限:虽然HTTP调用正常,但定时函数的服务账号可能缺少Firestore读取权限,需确认其拥有
datastore.databases.get、datastore.entities.list等相关权限。 - 调整函数超时设置:如果
firestore.get()操作耗时较长,而定时函数默认超时时间(1分钟)不足以支撑,可在控制台将超时时间延长至最大9分钟。
- 检查Pub/Sub触发函数的权限:虽然HTTP调用正常,但定时函数的服务账号可能缺少Firestore读取权限,需确认其拥有
内容的提问来源于stack exchange,提问作者Edward Cahyadi

