Firestore 查询永远不会在 Google 云事件触发函数内完成

Firestore query never completes inside Google Cloud Event Trigger Function

我有一个 Google Cloud Event Trigger Function 已经 运行 几个月了。不久前该功能开始失败,我一直在调查它。我已将其缩小为对特定 Firestore 集合从未完成的请求。

这是我用来进行故障排除的代码。除了控制台日志和对函数的调用以帮助我计算集合的大小(我在问题出现 之后添加了这两者)之外,我已经删除了所有内容。我可以 运行 使用当前备份在 Firebase Emulator 中做到这一点,并获得大约 6.5MB 的集合总大小。该集合中有 3001 个文档。

    let totalSize = 0;

    await admin
        .firestore()
        .collection("users")
        .get()
        .then(function(querySnapshot) {
          querySnapshot.forEach(function(doc) {
            console.log(doc.data().name);
            const bytes = sizeof(doc.data());
            totalSize += bytes;
          });
        });

    console.log("total size of the users collection: ", totalSize);
  },

当从 GCP 运行ning 时,该函数总是在 5 分钟后出错并显示这些函数日志:

Function execution took 222ms 行之后,它等待五分钟(这是 GCF 可以 运行 的最长时间)并给出 Unhandled rejection 错误。

如果我用任何其他集合替换 users 集合,它工作正常。

要么我太累了(最有可能),要么我的 Google-Fu 不是我想象的那样,或者我是第一个遇到这种情况的人(最不可能)。

当 运行在 Google 云函数中时,为什么 6.5MB 的集合永远不会 return?

更新:按要求添加日志(更改 project/location/function 名称)

insertId,labels.execution_id,logName,receiveTimestamp,resource.labels.function_name,resource.labels.project_id,resource.labels.region,resource.type,severity,textPayload,timestamp,trace
000000-57823b5d-a3c3-49c8-bca6-617f8ba6fbc4,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,ERROR,"Error: Process exited with code 16
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:96:22)
    at process.emit (events.js:400:28)
    at process.emit (domain.js:475:12)
    at process.exit (internal/process/per_thread.js:173:15)
    at sendCrashResponse (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/logger.js:38:9)
    at process.<anonymous> (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:92:44)
    at process.emit (events.js:400:28)
    at process.emit (domain.js:475:12)
    at processPromiseRejections (internal/process/promises.js:245:33)
    at processTicksAndRejections (internal/process/task_queues.js:96:32)",2022-01-26T14:19:56.798Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000009-b01ee32a-6f0e-4dc5-9d02-ddcbc955f8de,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,"    at processTicksAndRejections (internal/process/task_queues.js:95:5)",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000008-81c85f7d-e66e-4eb1-913c-f35578ea80fd,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,"    at /layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/function_wrappers.js:140:25",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000007-36da194f-7a44-4c98-a86b-54f8a85ee883,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,"    at cloudFunction (/workspace/node_modules/firebase-functions/lib/cloud-functions.js:134:23)",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000006-0a7895f7-3180-4b84-a8bc-4638108c2efd,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,"    at /workspace/_competingHorseActions/index.js:15:21",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000005-966bd66e-0725-42a9-aafa-f4f3d587a01a,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,"    at Object.createSearchesToDo (/workspace/_competingHorseActions/dataFunctions.js:16:10)",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000004-9efc598d-50e0-4b76-b084-b738e1149460,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,"    at CollectionReference.get (/workspace/node_modules/@google-cloud/firestore/build/src/reference.js:1438:21)",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000003-72ff7fe8-9b67-4cca-96bc-293d7cf71528,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,"    at CollectionReference._get (/workspace/node_modules/@google-cloud/firestore/build/src/reference.js:1449:23)",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000002-6b781252-5a83-4deb-9189-e257db5a96b7,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,Caused by: Error,2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000001-54f3eb45-17da-46e9-9420-ec9541a1de22,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,ERROR,"Error: 9 FAILED_PRECONDITION: The requested snapshot version is too old.
    at Object.callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:26)
    at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:331:49)
    at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
    at /workspace/node_modules/@grpc/grpc-js/build/src/call-stream.js:182:78
    at processTicksAndRejections (internal/process/task_queues.js:77:11)",2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000000-a62c012a-0e24-40cf-b18b-0e883577f022,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:20:05.306874125Z,myEventTriggerFunction,my-project,my-location,cloud_function,,Unhandled rejection,2022-01-26T14:19:55.541Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000000-475f9e2c-4cd8-4cc3-80d1-5ac7cf3dd12f,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:14:58.785021807Z,myEventTriggerFunction,my-project,my-location,cloud_function,DEBUG,"Function execution took 1272 ms, finished with status: 'ok'",2022-01-26T14:14:48.976106222Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000000-40548c05-e247-4de0-b876-5bec6b081452,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:14:58.785021807Z,myEventTriggerFunction,my-project,my-location,cloud_function,,createSearchesToDo Search,2022-01-26T14:14:48.966Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08
000000-ec65a497-72ac-4a87-9a00-4baba7b8c04e,ipijpyxnda0o,projects/my-project/logs/cloudfunctions.googleapis.com%2Fcloud-functions,2022-01-26T14:14:58.785021807Z,myEventTriggerFunction,my-project,my-location,cloud_function,DEBUG,Function execution started,2022-01-26T14:14:47.705838675Z,projects/my-project/traces/94a63d9f2e241b7bf1309eda7adf8f08

更新 2:我可以在几秒钟内使用 Firefoo 从 users 集合中将所有 ~3000 个文档提取到我的本地计算机。

似乎问题出在 users 集合本身,运行在 GCF 内部。

我也是 hyper-focused 在 .collection().get() 上,从来没有想过触发器的工作方式:

.onUpdate(async (change, context) => {
   //do stuff here
});

触发器本身是 async。从这里向我 运行 的函数调用添加一个 await 给了我预期的结果。

    .onUpdate(async (change, context) => {
      const result = await doTheStuff(context.params.id, change.after.data().name);
      console.log(result);
    });

doTheStuff 的内容现在看起来像这样并且可以正常工作。

async function doTheStuff(){
  console.log("-------------------------------------------------start");
  await admin
      .firestore()
      .collection("users")
      .get()
      .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
          console.log(doc.data().name);
        });
      })
      .catch((error) => {
        console.log(error);
      });
  console.log("-------------------------------------------------end");


  return "done with the stuff";
}

它在本地工作的事实误导了人们相信它不可能是代码问题,而实际上它是。

感谢那些有建议的人。

编辑

对承诺使用普遍接受的句法风格...

const db = admin.firestore();
try {
  const querySnapshot = await db.collection("users").get();
  querySnapshot.forEach(doc => {
    console.log(doc.data().name);
  });
} catch (error) {
  console.log(error);
}