使用 Firebase Cloud Functions 更新 Firestore 文档非常慢

问题描述 投票:0回答:1

我正在尝试使用 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 处理的数据。

flutter firebase google-cloud-firestore google-cloud-functions
1个回答
0
投票

您在更新 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...");
© www.soinside.com 2019 - 2024. All rights reserved.