Firebase Cloud Function Set Timeout 540s but ended at 60s
Asked Answered
C

1

6

I have my cloud function

import * as functions from 'firebase-functions';
const runtimeOpts = {
    timeoutSeconds: 540,
    memory: "1GB" as "1GB"

}
...
export const helloWorldAllowCORS = functions.runWith(runtimeOpts).https.onRequest(async (request, response) => {

    response.set('Access-Control-Allow-Origin', '*');
    response.set('Access-Control-Allow-Credentials', 'true'); // vital

    response.set('Keep-Alive', 'timeout=5, max=1000');

    if (request.method === 'OPTIONS') {
        // Send response to OPTIONS requests
        response.set('Access-Control-Allow-Methods', 'GET');
        response.set('Access-Control-Allow-Headers', 'Content-Type');
        response.set('Access-Control-Max-Age', '3600');
        response.status(204).send('');
    } else {
        let run = async (ms: any) => {
            await new Promise(resolve => setTimeout(resolve, ms));
        }
        await run(request.body.data.wait);

        response.send({
            data: {
                status: true
                , message: 'message v2 '
            }
        })
    }
});

And trigger from angular/fire plugin

 const callable = this.afFnc.httpsCallable("helloWorldAllowCORS");
    
    console.log(new Date());
 
    // wait for 3 min
    this.data = await callable({ wait: 180 * 1000 });

    this.data.subscribe(
      res => {
        console.log(new Date());
        console.log(res);
      },
      err => {
        console.log(new Date());
        console.error(err);
      }

end up chrome console showing timeout error in 1min

calling onTestCloudFunc()
2020-06-26T03:42:08.387Z
2020-06-26T03:43:18.401Z
Error: deadline-exceeded
    );

I have been stuck on the issue for few days. The official firebase doc doesn't tell much on handling CORS. Once integrated with angular/fire, the httpCallable func failed. And after i resolved the CORS issue by adding header. Then again, the new CORS bypass logic break the Timeout which supposed to run the process for 9mins.

I also tested, the firebase offical https://firebase.google.com/docs/functions can run more than 1 min if i increase the timeout. But the code can only run by manually copy & paste into chrome browser.

What i noticed, when firebase + angular/fire + cloud function + bypass CORS, the defined Timeout 540s will failed. Anyone have a fully integrated code references?

Appreciated in million~~ T_T...

Updates: I create a new onCall function Angular

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

Firebase Cloud Func, onCall method:

export const onCWaitASec = functions.runWith(runtimeOpts).https.onCall(async (data, context) => {
    
        let run = async (ms: any) => {
            await new Promise(resolve => setTimeout(resolve, ms));
        }
        await run(data.wait);

 return {
     status: 'success',
     message: `this is onCWaitASec() return msg waited ${data.wait} `
 }
})

Chrome Console

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

Firebase console also showing the timeout as 540s. And chrome console's two timestamp can proved that it timeout in 1 min enter image description here

Update as of 1 Jul Thankfully i got helps from Mau from Firebase support team, he managed to narrowed down the issue is with AngularFire package and not Firebase SDK itself. Here the latest working codes (using official Firebase JS SDK instead)

app.module.ts

import * as firebase from "firebase/app"; // official JS SDK
import { environment } from "../environments/environment";
if (!firebase.apps.length) {
   firebase.initializeApp(environment.firebaseConfig);
}

app.component.ts

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

Chrome console log

Angular is running in the development mode. Call enableProdMode() to enable the production mode.
callCloudFnOfficial() Start Trigger At:
2020-07-01T01:04:21.130Z
success at
2020-07-01T01:12:41.990Z
{data: {…}}
data: Object
message: "this is onCWaitASec() return msg waited 500000 "
status: "success"
__proto__: Object
__proto__: Object

As it finally able to execute for 500 seconds and return successfully. As compare to angular/fire's always return in 1 min

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

Chrome console

Start Trigger At:
2020-07-01T01:13:30.025Z
Error at
2020-07-01T01:14:40.037Z
Error: deadline-exceeded

Will also report as bug in AngularFire as it doesn't allow us to set timeout in client app. It's reported in firebase GitHub before. Here the resolution which i referred.

Church answered 26/6, 2020 at 3:54 Comment(0)
A
2

You've declared an HTTP function with onRequest:

export const helloWorldAllowCORS = functions.runWith(runtimeOpts).https
    .onRequest(async (request, response) => {

But you're trying to call it as a "callable" function, which is a different type of function:

const callable = this.afFnc.httpsCallable("helloWorldAllowCORS");

If be sure to note the difference between an HTTP function and a callable function by going over the linked documentation thoroughly. If you want to use an HTTP function, you should not call it with the client library used for callable functions. If you want to use a callable function, you should be using onCall, as shown in the docs.

Amianthus answered 26/6, 2020 at 5:8 Comment(2)
Thanks for the pointer @Doug, i created an onCall method and yet it still return in 1 min, when i purposely 'wait' for 3mins. Setups and codes been updated in original post.Church
sorry, anyone from Firebase dev team? or can i report it as bug? I really need help on this T.T...Church

© 2022 - 2024 — McMap. All rights reserved.