magician11
magician11

Reputation: 4634

Why is using Firebase Functions as an API endpoint so slow?

I built an app in Slack, that on interactions in Slack, will send an HTTP POST request to a URL. That URL is a Firebase Function that is triggered with an HTTP request.

The Firebase Function looks like this...

// process incoming shortcuts
exports.interactions = functions.https.onRequest(async (request, response) => {
  response.send();
  const payload = JSON.parse(request.body.payload);
  functions.logger.log(payload);

  if (payload.type === 'shortcut') {
    functions.logger.log('Found a shortcut...');
    const shortcuts = require('./shortcuts');
    await shortcuts(payload);
  } else if (payload.type === 'block_actions') {
    functions.logger.log('Found a block action...');
    const blockActions = require('./blockActions');
    await blockActions(payload);
  } else if (payload.type === 'view_submission') {
    functions.logger.log('Found a view submission...');
    const viewSubmissions = require('./viewSubmissions');
    await viewSubmissions(payload);
  }
  functions.logger.log('Done with interactions.');
});

The problem is, is that Firebase is taking 5-10 seconds to respond, and Slack is expecting a response in 3 seconds.

So the app in Slack erroring out.

Upvotes: 0

Views: 90

Answers (1)

magician11
magician11

Reputation: 4634

It turns out while I thought it would be useful to do a response.send() immediately when the function was called so that Slack had its instant response, I was then also inadvertently starting background activities in Firebase.

The line in the above Firebase docs that gave me the biggest clue was:

Background activity can often be detected in logs from individual invocations, by finding anything that is logged after the line saying that the invocation finished.

Which I found here... the function started, and completed, and then the code to open a modal began to be executed...

enter image description here

I then found in the Firebase docs

Terminate HTTP functions with res.redirect(), res.send(), or res.end().

So all I really had to do was move response.send() to the end of the function. Also I had to make sure that I had await statements before my async functions, so that async functions waited to be resolved before executing the final response.send()

// process incoming shortcuts
exports.interactions = functions.https.onRequest(async (request, response) => {
  const payload = JSON.parse(request.body.payload);
  functions.logger.log(payload);

  if (payload.type === 'shortcut') {
    functions.logger.log('Found a shortcut...');
    const shortcuts = require('./shortcuts');
    await shortcuts(payload);
  } else if (payload.type === 'block_actions') {
    functions.logger.log('Found a block action...');
    const blockActions = require('./blockActions');
    await blockActions(payload);
  } else if (payload.type === 'view_submission') {
    functions.logger.log('Found a view submission...');
    const viewSubmissions = require('./viewSubmissions');
    await viewSubmissions(payload);
  }
  functions.logger.log('Done with interactions.');
  response.send();
});

The modal interaction response times in Slack are much quicker and usable now.

Upvotes: 1

Related Questions