我正在尝试使用 Firebase Cloud Functions 更新文档。我的文档更新不需要考虑现有值,并且由于它们主要涉及单个文档更新,冲突风险最小,因此我将继续进行而不进行事务处理。
问题是,即使是单个测试用例也需要大约 3 分钟才能完成。作为一名初级开发人员,我以前从未在 Cloud Functions 中遇到过此类延迟,并且我正在努力找出问题的根本原因。
下面是我的完整代码以及从中生成的日志:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.authenticator = functions.region('asia-northeast1').https.onRequest(async (req, res) => {
const startTime = new Date().getTime();
console.log("Function execution started at: ", new Date().toISOString());
if (req.method !== "POST") {
console.log("Method Not Allowed");
return res.status(405).send("Method Not Allowed");
}
const data = req.body;
if (!data || !data.data || !Array.isArray(data.data)) {
console.log("Bad Request");
return res.status(400).send("Bad Request");
}
res.status(200).send("Processing...");
console.log("Process started at: ", new Date().toISOString());
for (const item of data.data) {
if (!item || !item.phoneNum || !item.authCode) {
console.log("Invalid data: ", item);
continue;
}
try {
const updateStart = new Date().getTime();
console.log("Update started for authCode: ", item.authCode, " at: ", new Date().toISOString());
await admin.firestore().collection("auth").doc(item.authCode).update({
phoneNum: item.phoneNum,
verified: true,
timestamp: admin.firestore.FieldValue.serverTimestamp()
});
const updateEnd = new Date().getTime();
console.log("Success: ", item.authCode, " at: ", new Date().toISOString(), " Update took: ", (updateEnd - updateStart) / 1000, " seconds");
} catch (err) {
console.error(`Error processing ${item.authCode}:`, err);
}
}
const endTime = new Date().getTime();
console.log("Process ended at: ", new Date().toISOString());
console.log("Total execution time: ", (endTime - startTime) / 1000, " seconds");
});
函数执行开始函数执行开始于:2024-07-09T21:28:39.167Z
流程开始于:2024-07-09T21:28:39.188Z
已开始更新 authCode:519504f79458497cb8c4709739fbc877,时间:2024-07-09T21:28:39.188Z
函数执行花费了 80 毫秒,完成状态代码:200
成功:519504f79458497cb8c4709739fbc877于:2024-07-09T21:31:36.657Z
更新耗时:177.469 秒
流程结束于:2024-07-09T21:31:36.957Z
总执行时间:177.79秒
我的 Cloud Functions 的区域是 asia-northeast1,Firestore 位于 asia-northeast3。由于担心潜在的区域相关问题,我更改了区域,但我之前甚至在 us-central1 区域也快速处理了更新。
供您参考,我的代码通过来自 Google Apps 脚本的 POST 请求接收由 Gmail 处理的数据。
您在更新 Firestore 之前发送
res.status(200).send("Processing...");
。鉴于此,如果任何文档更新能够成功,那你就很幸运了。
将向客户端发送响应的代码移至更新所有文档之后。
此外,您现在在每次调用时使用
await
来更新数据库,这意味着所有更新都是按顺序执行的 - 一个接着一个。由于数据似乎不需要这样做,因此如果并行更新它们会更快。最简单的方法是将所有 updateDoc
承诺收集在一个数组中,然后在该数组上收集 await Promise.all(...)
。
console.log("Process started at: ", new Date().toISOString());
const promises = [];
for (const item of data.data) {
if (!item || !item.phoneNum || !item.authCode) {
console.log("Invalid data: ", item);
continue;
}
try {
promises.push(admin.firestore().collection("auth").doc(item.authCode).update({
phoneNum: item.phoneNum,
verified: true,
timestamp: admin.firestore.FieldValue.serverTimestamp()
}));
} catch (err) {
console.error(`Error processing ${item.authCode}:`, err);
}
}
await Promise.all(promises);
const endTime = new Date().getTime();
console.log("Process ended at: ", new Date().toISOString());
console.log("Total execution time: ", (endTime - startTime) / 1000, " seconds");
res.status(200).send("Processing...");