Firebase Cloud Function 设置超时 540 秒,但在 60 秒结束

Wei*_*ies 6 firebase google-cloud-functions angularfire2

我有我的云功能

\n
import * as functions from \'firebase-functions\';\nconst runtimeOpts = {\n    timeoutSeconds: 540,\n    memory: "1GB" as "1GB"\n\n}\n...\nexport const helloWorldAllowCORS = functions.runWith(runtimeOpts).https.onRequest(async (request, response) => {\n\n    response.set(\'Access-Control-Allow-Origin\', \'*\');\n    response.set(\'Access-Control-Allow-Credentials\', \'true\'); // vital\n\n    response.set(\'Keep-Alive\', \'timeout=5, max=1000\');\n\n    if (request.method === \'OPTIONS\') {\n        // Send response to OPTIONS requests\n        response.set(\'Access-Control-Allow-Methods\', \'GET\');\n        response.set(\'Access-Control-Allow-Headers\', \'Content-Type\');\n        response.set(\'Access-Control-Max-Age\', \'3600\');\n        response.status(204).send(\'\');\n    } else {\n        let run = async (ms: any) => {\n            await new Promise(resolve => setTimeout(resolve, ms));\n        }\n        await run(request.body.data.wait);\n\n        response.send({\n            data: {\n                status: true\n                , message: \'message v2 \'\n            }\n        })\n    }\n});\n
Run Code Online (Sandbox Code Playgroud)\n

并从 Angular/Fire 插件触发

\n
 const callable = this.afFnc.httpsCallable("helloWorldAllowCORS");\n    \n    console.log(new Date());\n \n    // wait for 3 min\n    this.data = await callable({ wait: 180 * 1000 });\n\n    this.data.subscribe(\n      res => {\n        console.log(new Date());\n        console.log(res);\n      },\n      err => {\n        console.log(new Date());\n        console.error(err);\n      }\n
Run Code Online (Sandbox Code Playgroud)\n

最终 chrome 控制台在 1 分钟内显示超时错误

\n
calling onTestCloudFunc()\n2020-06-26T03:42:08.387Z\n2020-06-26T03:43:18.401Z\nError: deadline-exceeded\n    );\n
Run Code Online (Sandbox Code Playgroud)\n

我已经被这个问题困扰了好几天了。Firebase 官方文档没有详细介绍如何处理 CORS。一旦与 Angular/Fire 集成,httpCallable 函数就会失败。在我通过添加 header 解决了 CORS 问题之后。然而,新的 CORS 旁路逻辑再次打破了本应运行该进程 9 分钟的超时。

\n

我还测试了,如果我增加超时,firebase官方https://firebase.google.com/docs/functions可以运行超过1分钟。但该代码只能通过手动复制并粘贴到 Chrome 浏览器中来运行。

\n

我注意到,当 firebase + Angular/fire + 云功能 + 绕过 CORS 时,定义的超时 540 秒将失败。有人有完全集成的代码参考吗?

\n

赞赏百万~~T_T...

\n

更新: \n我创建了一个新的 onCall 函数\nAngular

\n
console.log(\'Start Time: \', new Date());\n// wait for 3 min\n    const callable = this.afFnc.httpsCallable("onCWaitASec");\n    this.data = await callable({ wait: 3 * 60 * 1000 });\nthis.data.subscribe(\n  res => {\n    console.log(new Date());\n    console.log(res);\n  },\n  err => {\n    console.log(new Date());\n    console.error(err);\n  }\n);\n
Run Code Online (Sandbox Code Playgroud)\n

Firebase Cloud Func,onCall 方法:

\n
export const onCWaitASec = functions.runWith(runtimeOpts).https.onCall(async (data, context) => {\n    \n        let run = async (ms: any) => {\n            await new Promise(resolve => setTimeout(resolve, ms));\n        }\n        await run(data.wait);\n\n return {\n     status: \'success\',\n     message: `this is onCWaitASec() return msg waited ${data.wait} `\n }\n})\n
Run Code Online (Sandbox Code Playgroud)\n

Chrome 控制台

\n
Start Time:  Fri Jun 26 2020 14:42:56 GMT+0800 (Singapore Standard Time)\nlogin.component.ts:128 Fri Jun 26 2020 14:44:07 GMT+0800 (Singapore Standard Time)\nlogin.component.ts:129 Error: deadline-exceeded\n    at new HttpsErrorImpl (index.cjs.js:58)\n    at index.cjs.js:373\n    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)\n    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)\n    at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:503)\n    at ZoneTask.invoke (zone.js:492)\n    at timer (zone.js:3034)\n
Run Code Online (Sandbox Code Playgroud)\n

Firebase 控制台还显示超时为 540 秒。而chrome控制台的两个时间戳可以证明它在1分钟内超时\n在此输入图像描述

\n

截至 7 月 1 日更新\n值得庆幸的是,我得到了 Firebase 支持团队 Mau 的帮助,他设法缩小了问题范围,是与 AngularFire 包有关,而不是与 Firebase SDK 本身有关。这里是最新的工作代码(使用官方 Firebase JS SDK 代替)

\n

应用程序模块.ts

\n
import * as firebase from "firebase/app"; // official JS SDK\nimport { environment } from "../environments/environment";\nif (!firebase.apps.length) {\n   firebase.initializeApp(environment.firebaseConfig);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

应用程序组件.ts

\n
import * as firebase from "firebase/app";\nimport "firebase/functions";\n...\n  async callCloudFnOfficial() {\n    console.log("callCloudFnOfficial() Start Trigger At: ", new Date());\nvar callable = firebase.functions().httpsCallable("onCWaitASec", {timeout: 540000});\n    callable({ wait: 500 * 1000 })\n      .then(function(res) {\n        console.log("success at ", new Date());\n        console.log(res);\n      })\n      .catch(function(error) {\n        console.log("Error at ", new Date());\n        console.error(error);\n      });\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

Chrome 控制台日志

\n
Angular is running in the development mode. Call enableProdMode() to enable the production mode.\ncallCloudFnOfficial() Start Trigger At:\n2020-07-01T01:04:21.130Z\nsuccess at\n2020-07-01T01:12:41.990Z\n{data: {\xe2\x80\xa6}}\ndata: Object\nmessage: "this is onCWaitASec() return msg waited 500000 "\nstatus: "success"\n__proto__: Object\n__proto__: Object\n
Run Code Online (Sandbox Code Playgroud)\n

因为它终于能够执行500秒并成功返回。与 Angular/Fire 相比,它总是在 1 分钟内返回

\n
import { AngularFireFunctions } from "@angular/fire/functions";\n...\n  async callCloudFn() {\n    console.log("Start Trigger At: ", new Date());\n    const callable = this.fns.httpsCallable("onCWaitASec");\n    // delay return for X seconds\n    let cloudFncResp: Observable<any> = await callable({ wait: 500 * 1000 });\n    cloudFncResp.subscribe(\n      res => {\n        console.log("success at ", new Date());\n        console.log(res);\n      },\n      error => {\n        console.log("Error at ", new Date());\n        console.error(error);\n      }\n    );\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

Chrome 控制台

\n
Start Trigger At:\n2020-07-01T01:13:30.025Z\nError at\n2020-07-01T01:14:40.037Z\nError: deadline-exceeded\n
Run Code Online (Sandbox Code Playgroud)\n

还将报告 AngularFire 中的错误,因为它不允许我们在客户端应用程序中设置超时。之前曾在 firebase GitHub 中报道过。这是我提到的决议。

\n

Dou*_*son 2

您已经使用 onRequest 声明了一个 HTTP 函数:

export const helloWorldAllowCORS = functions.runWith(runtimeOpts).https
    .onRequest(async (request, response) => {
Run Code Online (Sandbox Code Playgroud)

但是您尝试将其称为“可调用”函数,这是一种不同类型的函数:

const callable = this.afFnc.httpsCallable("helloWorldAllowCORS");
Run Code Online (Sandbox Code Playgroud)

请务必通过彻底查看链接文档来注意HTTP 函数可调用函数之间的区别。如果要使用 HTTP 函数,则不应使用用于可调用函数的客户端库来调用它。如果您想使用可调用函数,则应该使用 onCall,如文档中所示。