Firebase Cloud Function超时60000ms,导出Collection至Cloud Storage失败
问题:Cloud Function导出Firestore集合到Cloud Storage超时无文件生成
我尝试用Cloud Function将Firestore里的data/analytics/hosts集合导出为CSV并保存到Cloud Storage,部署了如下函数后,日志仅显示超时,但Cloud Storage中未生成任何文件:
const functions = require("firebase-functions"); const firebase = require("firebase-admin"); const { parseAsync } = require('json2csv'); const { v4: uuidv4 } = require('uuid'); const fs = require("fs"); const path = require("path"); const os = require("os"); const generateHostsCsv = functions.region("europe-west1").pubsub .topic("generate-hosts-csv") .onPublish(async message => { // 获取Firestore集合文档 const hostsSnapshot = await firebase .firestore() .collection("data") .doc("analytics") .collection("hosts") .get(); const hosts = hostsSnapshot.docs.map(doc => doc.data()); // CSV字段头部 const fields = [ "hostName", "count", ]; // 生成CSV内容 const output = await parseAsync(hosts, { fields }); // 生成文件名 const dateTime = new Date().toISOString().replace(/\W/g, ""); const filename = `hosts_${dateTime}.csv`; const tempLocalFile = path.join(os.tmpdir(), filename); return new Promise((resolve, reject) => { // 将CSV写入临时文件 fs.writeFile(tempLocalFile, output, error => { if (error) { reject(error); return; } const bucket = firebase.storage().bucket(); // 上传到默认存储桶 bucket .upload(tempLocalFile, { metadata: { metadata: { firebaseStorageDownloadTokens: uuidv4(), } }, }) .then(() => resolve()) .catch(errorr => reject(errorr)); }); }); }); module.exports = { generateHostsCsv };
错误日志
Function execution took 60000 ms, finished with status: 'timeout'
排查方向与修复方案
缺失Firebase Admin SDK初始化
代码中未初始化Admin SDK,导致Firestore和Storage调用失败,需在函数顶部添加:firebase.initializeApp();权限不足
Cloud Function的默认服务账号需要具备:Cloud Datastore User权限(读取Firestore)Storage Object Creator权限(写入Cloud Storage)
前往IAM页面给对应服务账号添加上述角色。
异步操作处理不当
原代码用回调式fs.writeFile包裹Promise,易出现Promise未正确解析的问题,改用Promise化API简化逻辑:// 替换原Promise包裹的写入与上传逻辑 await fs.promises.writeFile(tempLocalFile, output); const bucket = firebase.storage().bucket(); await bucket.upload(tempLocalFile, { metadata: { metadata: { firebaseStorageDownloadTokens: uuidv4(), } }, }); // 清理临时文件 await fs.promises.unlink(tempLocalFile);集合数据量过大导致超时
如果hosts集合文档数量多,一次性get()会拉取全部数据引发超时,需改用分页查询分批处理:// 分页查询示例 let lastDoc = null; const hosts = []; do { const query = firebase.firestore() .collection("data") .doc("analytics") .collection("hosts") .limit(500); // 每次拉取500条 const snapshot = lastDoc ? await query.startAfter(lastDoc).get() : await query.get(); if (snapshot.empty) break; hosts.push(...snapshot.docs.map(doc => doc.data())); lastDoc = snapshot.docs[snapshot.docs.length - 1]; } while (true);
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

