错误:超出截止日期 - 调用 firebase 可调用云函数 (onCall) 时。onRequest 工作正常

Cam*_*opy 4 javascript firebase google-cloud-functions

调用 firebase 可调用云函数 (onCall) 时,我在前端收到“超过截止日期”错误。

\n\n

我知道我必须返回一个 Promise,以便该函数知道何时清理自身,但它仍然不起作用。

\n\n

60 秒后,“deadline-exceeded”被抛出到前端,但该函数继续在服务器上运行并成功完成。所有批处理操作都会写入 firestore。

\n\n
10:37:14.782 AM\nsyncExchangeOperations\nFunction execution took 319445 ms, finished with status code: 200\n10:36:57.323 AM\nsyncExchangeOperations\nFunction execution started\n10:36:57.124 AM\nsyncExchangeOperations\nFunction execution took 170 ms, finished with status code: 204\n10:36:56.955 AM\nsyncExchangeOperations\nFunction execution started\n
Run Code Online (Sandbox Code Playgroud)\n\n
async function syncBinanceOperations(\n  userId,\n  userExchange,\n  userExchangeLastOperations,\n  systemExchange\n) {\n  try {\n    const client = Binance({\n      apiKey: userExchange.apiKey,\n      apiSecret: userExchange.privateKey\n    });\n\n    const batch = admin.firestore().batch();\n    const lastOperations = userExchangeLastOperations\n      ? userExchangeLastOperations\n      : false;\n\n    const promises = [];\n\n    promises.push(\n      syncBinanceTrades(client, lastOperations, userId, systemExchange, batch)\n    );\n    promises.push(\n      syncBinanceDeposits(client, lastOperations, userId, systemExchange, batch)\n    );\n    promises.push(\n      syncBinanceWhitdraws(\n        client,\n        lastOperations,\n        userId,\n        systemExchange,\n        batch\n      )\n    );\n    promises.push(\n      updateUserExchange(userId, userExchange.id, {\n        lastSync: moment().format(\'x\')\n      })\n    );\n\n    await Promise.all(promises);\n    return batch.commit();\n  } catch (error) {\n    return handleErrors(error);\n  }\n}\n\nexports.syncExchangeOperations = functions.https.onCall(\n  async (data, context) => {\n    try {\n      userAuthenthication(data.userId, context.auth);\n      let user = await getUser(data.userId);\n\n      if (!user.plan.benefits.syncExchanges) {\n        throw \'Opera\xc3\xa7\xc3\xa3o n\xc3\xa3o autorizada para o plano contratado\';\n      }\n\n      let userExchange = await getUserExchange(data.userId, data.exchangeId);\n\n      let response = await Promise.all([\n        getUserLastOperations(data.userId, userExchange.exchangeId),\n        getSystemExchange(userExchange.exchangeId)\n      ]);\n\n      let userExchangeLastOperations = response[0];\n      let systemExchange = response[1];\n\n      switch (systemExchange.id) {\n        case \'binance\':\n          return syncBinanceOperations(\n            user.id,\n            userExchange,\n            userExchangeLastOperations,\n            systemExchange\n          );\n      }\n    } catch (error) {\n      return handleErrors(error);\n    }\n  }\n);\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我将此函数更改为 HTTP 请求,则效果很好。它等待函数完成并返回。

\n\n
exports.syncExchangeOperations = functions\n  .runWith(runtimeOpts)\n  .https.onRequest((req, res) => {\n    return cors(req, res, async () => {\n      try {\n        let auth = await admin.auth().verifyIdToken(req.get(\'Authorization\').split(\'Bearer \')[1]);\n\n        let userExchange = await getUserExchange(\n          auth.uid,\n          req.query.exchangeId\n        );\n\n        let response = await Promise.all([\n          getUserLastOperations(auth.uid, userExchange.exchangeId),\n          getSystemExchange(userExchange.exchangeId)\n        ]);\n\n        let userExchangeLastOperations = response[0];\n        let systemExchange = response[1];\n\n        switch (systemExchange.id) {\n          case \'binance\':\n            await syncBinanceOperations(\n              auth.uid,\n              userExchange,\n              userExchangeLastOperations,\n              systemExchange\n            );\n        }\n        res.status(200).send();\n      } catch (error) {\n        res.status(401).send(handleErrors(error));\n      }\n    });\n  });\n
Run Code Online (Sandbox Code Playgroud)\n

小智 23

您遇到的“ deadline -exeeded”是客户端上的 Firebase Javascript 库(而不是函数本身)抛出的错误。Firebase 文档缺少如何在可调用函数上使用functions.runWithOptions()的文档。由于某种原因,functions().httpsCallable()在客户端有一个内置的超时。

因此,如果您在Node.js 函数上使用它:

exports.testFunction = functions.runWith({ timeoutSeconds: 180 }).https.onCall(async (data, ctx) => {
// Your Function Code that takes more than 60second to run
});
Run Code Online (Sandbox Code Playgroud)

您需要在客户端上覆盖Javascript 库超时中的 buit,如下所示:

let testFunction = firebase.functions().httpsCallable("testFunction", {timeout: 180000});
Run Code Online (Sandbox Code Playgroud)

我不知道客户端内置超时的目的是什么,对我来说它没有任何目的,因为它甚至不会停止服务器上函数的执行。但它的存在一定是出于某些内部原因。

请注意,Node.js timeoutSeconds为单位,客户端库上的超时选项以毫秒为单位。

  • 一个传奇的答案谢谢——这会节省我很多时间 (2认同)