用户活动后,Google Cloud Function 的 Firestore 查询速度变慢

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

我有一个查询 Firestore 的 Google Cloud Function (GCF)。我还有一个用户可以读取/写入 Firestore 的应用程序。在用户使用我的应用程序之前,GCF 工作正常。用户活动几分钟后,GCF 中的查询开始花费很长时间。例如,在 GCF 中,对文档的简单更新将花费 27 秒。

即使用户活动停止几分钟后,GCF 的查询仍然很慢。这是为什么?

代码:

exports.processDocument = functions
  .runWith({ timeoutSeconds: 120 })
  .https.onRequest(async (req, res) => {
    const { documentId } = req.body;
    const id = req.body.documentId;

    if (!documentId) {
      return res.status(400).send("Missing documentId");
    }

    // Send a 200 response immediately
    res.status(200).send("Processing document...");

    const db = admin.firestore();
    const oneMindDocRef = db.collection("OneMind").doc(documentId);

    console.log(id, `Setting ${oneMindDocRef.id} document to being processed.`);
    await oneMindDocRef.update({
      processing: true,
      votingUsers: [],
    });
    console.log(id, `Set ${oneMindDocRef.id} document to being processed.`);

    const oneMindDoc = await oneMindDocRef.get();
    console.log(id, "Got OneMind document data");

    const activeUsers = oneMindDoc.data().activeUsers;
    const roundNumber = oneMindDoc.data().roundNumber;
    console.log(id, "Got activeUsers and roundNumber");

    if (!activeUsers || activeUsers.length === 0) {
      console.log(
        id,
        `No active users. Resetting ${oneMindDocRef.id} document.`
      );
      await oneMindDocRef.update({
        lastUpdated: admin.firestore.FieldValue.serverTimestamp(),
        processing: false,
        activeUsersCount: 0,
        activeUsers: [],
      });
      console.log(id, `${oneMindDocRef.id} document reset.`);

      console.log(`Document ${oneMindDocRef.id} reset due to no active users.`);
      return;
    }
    const proposedMessagesRef = db.collection("proposedMessages");

    if (oneMindDoc.data().userFeedbackMechanism == "slider") {
      await calculateWeightedAverageScores(db, documentId);
    }

    const proposedMessagesDocs = await proposedMessagesRef
      .where("roundNumber", "==", roundNumber)
      .where("chatroomName", "==", oneMindDoc.data().chatroomName)
      .orderBy("votes", "desc")
      .orderBy("creation", "asc")
      .get();

    console.log(id, "Got all proposed messages for the current round.");
    if (proposedMessagesDocs.docs.length === 0) {
      await oneMindDocRef.update({
        activeUsers: [],
        activeUsersCount: 0,
        lastUpdated: admin.firestore.FieldValue.serverTimestamp(),
        processing: false,
      });
      console.log(
        id,
        `${oneMindDocRef.id} document reset due to no proposed messages.`
      );

      console.log(
        `Document ${oneMindDocRef.id} reset due to no proposed messages.`
      );
      return;
    }

    const highestVotedMessageDoc = proposedMessagesDocs.docs[0];
    const highestVotedMessageData = highestVotedMessageDoc.data();

    console.log(id, 'Adding winning message to "messages" collection');
    const {
      message,
      creation,
      translatedText,
      creator,
      imageUrl,
      chatroomName,
      speaker,
    } = highestVotedMessageData;

    const messageRef = db.collection("messages").doc();
    const messageData = {
      creation: creation,
      creator: creator,
      speaker: speaker,
      roundNumber: roundNumber,
    };
    console.log("New message doc id: ", messageRef.id);

    if (imageUrl) {
      messageData.imageUrl = imageUrl;
    }

    if (message) {
      messageData.message = message;
    }

    if (translatedText) {
      messageData.translatedText = translatedText;
    }

    if (chatroomName) {
      messageData.chatroomName = chatroomName;
    }

    await messageRef.set(messageData);
    console.log(id, "New document created in messages collection.");

    let newCurrentSpeaker = oneMindDoc.data().currentSpeaker;
    if (oneMindDoc.data().chatroomName !== "OneMind") {
      newCurrentSpeaker =
        newCurrentSpeaker === oneMindDoc.data().team1
          ? oneMindDoc.data().team2
          : oneMindDoc.data().team1;
      console.log(
        `Updating current speaker from ${
          oneMindDoc.data().currentSpeaker
        } to ${newCurrentSpeaker}`
      );
    }

    console.log(id, `Resetting ${oneMindDocRef.id} document for next message`);
    await oneMindDocRef.update({
      activeUsers: [],
      activeUsersCount: 0,
      lastUpdated: admin.firestore.FieldValue.serverTimestamp(),
      processing: false,
      currentSpeaker: newCurrentSpeaker,
      roundNumber: admin.firestore.FieldValue.increment(1),
    });
    console.log(id, `${oneMindDocRef.id} document reset.`);
  });

日志:

2024-10-10 18:31:05.099 EDT processDocument4873x1mfdaij Function execution started
2024-10-10 18:31:05.256 EDT processDocument4873x1mfdaij about to start waiting
2024-10-10 18:31:05.257 EDT processDocument4873x1mfdaij done waiting
2024-10-10 18:31:05.257 EDT processDocument4873x1mfdaij Function execution took 157 ms, finished with status code: 200
2024-10-10 18:31:05.257 EDT processDocument4873x1mfdaij OneMind Setting OneMind document to being processed.
2024-10-10 18:31:07.955 EDT processDocument4873x1mfdaij OneMind Set OneMind document to being processed.
2024-10-10 18:31:34.255 EDT processDocument4873x1mfdaij OneMind Got OneMind document data
2024-10-10 18:31:41.855 EDT processDocument4873x1mfdaij OneMind Got activeUsers and roundNumber
2024-10-10 18:31:41.855 EDT processDocument4873x1mfdaij OneMind No active users. Resetting OneMind document.
2024-10-10 18:31:51.860 EDT processDocument4873x1mfdaij OneMind OneMind document reset.
2024-10-10 18:31:51.860 EDT processDocument4873x1mfdaij Document OneMind reset due to no active users.

请注意最后两行代码相隔 27 秒,但其间发生的只是我更新了 Firestore 中的文档。

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

问题是您在所有工作完成之前发送响应。 Cloud Functions 不支持在响应完成后执行“后台”工作。 发送响应有效终止该功能:

通过正确终止函数,您可以避免运行时间过长或无限循环的函数产生过多费用。此外,您还可以确保在您的函数成功达到其终止条件或状态之前,运行您的函数的 Cloud Functions 实例不会关闭。

使用 res.redirect()、res.send() 或 res.end() 终止 HTTP 函数。

事实上,您可以预期,在发送响应之前未完成的任何“悬空”工作都会表现得不稳定或根本不表现。

为了正确实现此功能,您应该等待所有工作完成后再发送最终响应。

© www.soinside.com 2019 - 2024. All rights reserved.