Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloud Functions for Firebase performance

I'm using Cloud Functions for Firebase to:

  1. Receive parameters from api.ai
  2. Make a call to a third-party API and
  3. Respond back to api.ai.

My call to the third-party API uses the request Node.js module and is wrapped within a function (getInfoFromApi()) in index.js.

The problem I'm having is that the execution of the secondary function call is consistently taking between 15-20 seconds. Note: The cloud function itself completes its execution consistently in the 400 ms range.

By logging simple comments to the console I can see when the function starts, when the secondary function is being called and when it receives a response from the third party, so I think I can see what's happening.

Roughly, the timings look like this:

  • 0: cloud function initialises
  • 400 ms: cloud function completes
  • 16 s: getInfoFromApi() function is called (!)
  • 17 s: third-party API returns results

My questions:

  • Is there an obvious reason for the delay in calling the secondary function? This doesn't seem to be caused by the cold start issue since the cloud function springs to life quickly and the delay is consistent even after repeated calls.
  • Is the use of the 'request' node module causing the issue? Is there a better module for creating/managing http requests from cloud functions?

You can see a simplified Gist of the index.js here: https://gist.github.com/anonymous/7e00420cf2623b33b80d88880be04f65

Here is a grab of the Firebase console showing example timings. Note: the output is slightly different from the above code as I simplified the above code to help understanding. enter image description here

like image 395
James Avatar asked Nov 08 '22 00:11

James


1 Answers

The getInfoFrom3rdParty() call is an asynchronous event. However, you haven't returned a promise from your function, so Functions is not waiting for the async event to complete.

It looks to me like, since you are returning undefined, the Function also assumes that it failed and retries. At some point in the retry process, the async event is probably completing before the function exits (i.e. unintentional success due to race conditions). I've seen similar outcomes in other cases where users don't return a promise or value in their functions.

I can't tell from the gist what you're trying to do--it doesn't appear to actually do anything with the third party results and probably isn't a realistic mcve of your use case. But something like this is probably what you want:

exports.getInfo = functions.https.onRequest((request, response) => {
  // ....

  // NOTE THE RETURN; MOST IMPORTANT PART OF THIS SAMPLE
  return getInfoFromThirdParty(...).then(() => {
    response.writeHead(200, {"Content-Type": "application/json"});
    response.end(JSON.stringify(payload));
  }).catch(e => /* write error to response */);
});

function getInfoFrom3rdParty(food) {
  reqObj.body = '{"query": "'+food+'"}';

  return new Promise((resolve, reject) => {
       mainRequest(reqObj, function (error, response, body) {
          // ....
          if( error ) reject(error);
          else resolve(...);
          // ....
       });
  });
}
like image 176
Kato Avatar answered Nov 14 '22 21:11

Kato