1

I have a firebase v2 function set to timeout in 540 seconds however httpsCallableFromURL catches with an error saying Firebase Error: deadline-exceeded before the function finishes.

Here's the template of my firebase function:

exports.functionname = functions.https.onCall(
  {
    timeoutSeconds: 540,
    cpu: 2,
  },
  async (req) => { 
  
    const getOutput = async (id: string) => {
      return new Promise((resolve, reject) => {
        return axios.get('ur'l)
          .then((res) => {
            resolve(res.data)
          })
          .catch((e) => {
            resolve(false)
          })
      })
    }

    let output: any

    const recurse = async () => {
      return new Promise(async (resolve) => {
        // first try getting output
        output = await getOutput(id).then((res) => {
          return res
        })

        // check for output
        if (output.output) {
          return resolve(true)
        } else if (output.error) {
          return resolve(false)
        } else {
          setTimeout(() => {
            return resolve(recurse())
          }, 2000)
        }
      })
    }

    return recurse()
      .then(async () => {
        const imageUrl = output.output[0]

        function getBase64(url: string) {
          return axios
            .get(url, {
              responseType: 'arraybuffer',
            })
            .then((response) =>
              Buffer.from(response.data, 'binary').toString('base64'),
            )
        }

        const base64Image = await getBase64(imageUrl)

        const data = {
          type: 'image',
          predictionId,
          result: base64Image,
        }

        return data
        }
      })
      .catch((e) => {
        return false
      })

 },
)

If I monitor the function logs it ends up finishing within the 540 seconds but my client never receives the return value since the httpsCallableFromURL errored out.

cormacncheese
  • 1,251
  • 1
  • 13
  • 27
  • If possible can you also share the full function code by editing the question as this kind of error usually occurs with the quota exceeds for firestore according to this [thread](https://stackoverflow.com/a/67716991/20239914) – Rohit Kharche Dec 23 '22 at 07:22
  • As Rohit mentioned you should share the entire code of your cloud Function. If you don't correctly [manage the CF life cycle](https://firebase.google.com/docs/functions/terminate-functions) you may encounter this kind of problem. – Renaud Tarnec Dec 23 '22 at 12:16
  • thanks @RohitKharche just added the function body. I'm not using firestore but am implementing recursion – cormacncheese Dec 24 '22 at 15:38
  • @RenaudTarnec could you elaborate? I am returning a promise in my firebase function and am still facing this error – cormacncheese Jan 05 '23 at 22:53
  • 1
    I recommend reviewing [this thread](https://stackoverflow.com/questions/43036229) and this [Promises rundown](https://web.dev/promises/). There are a number of errors in your code caused by improper use of Promises and how you've chained actions together. – samthecodingman Jan 06 '23 at 07:07

2 Answers2

0

This issue involves some debugging with calculating execution time for each Promise because your Error is related to the timeout that is specified in the function which is 540 sec means all of your promises should be resolved or rejected in the given 540 secs.

So I will recommend you to place some console.time(“Promise 1”) and console.timeEnd(“Promise 1”) around each Promises so we can get expected execution time for each promise and compare the total execution time of function and with this data you can modify the the corresponding promise which takes a lot of time. For more about this topic go through this thread

And In the end If above all doesn’t work then you can just increase the timeout to 1800 sec means 30 mins to complete all the execution within the given timeout, but this should be avoided as a best practice.

Rohit Kharche
  • 2,541
  • 1
  • 2
  • 13
0

Found the original answer which explains you need to override the timeout parameter on the client side as well.

exports. functionname = functions.runWith({ timeoutSeconds: 180 }).https.onCall(async (data, ctx) => {
   // Your Function Code that takes more than 120 second to run
});

then on the client side:

firebase.functions().httpsCallable("testFunction", {timeout: 180000});
cormacncheese
  • 1,251
  • 1
  • 13
  • 27