1

I'm building an express server using the cloud functions, but I facing a problem with res.send(). In a common express server I can exec some code after res.send() but at my express server using the Firebase cloudFunctions res.send() closes my connection and I can't exec anything after that.

Here is what I need to do: In my server I have an endpoint to receive some data from Slack api dialog, and after that Slack Api is waiting for a empty response res.send(), so I need to send it. But I also need to save that data in my DB, and send a message in slack to my user "Your post was saved!" So what my endpoint does:

async function myEndpoint(req, res) {
    await savePayload(req.payload);
    await sendUserMessage(req.payload);
    res.send('');
}

But sometimes res.send() takes to long to start running and I get an error on slack, so I would like to do something like:

async function myEndpoint(req, res) {
    res.send('');
    await savePayload(req.payload);
    await sendUserMessage(req.payload);
}

But as I said, after res.send('') my connection is closed and the next lines doesn't run. Do you know how can I work around that ?

Lucas Andrade
  • 4,315
  • 5
  • 29
  • 50

1 Answers1

3

HTTP functions immediately terminate execution once the response is completed -- this is fundamental architecture for Cloud Functions, so there is no way around it. You will need to either:

  1. Optimize your code paths such that the empty response is always sent under the deadline, or
  2. Trigger a background function execution that will do the work asynchronously, then respond. This could be done by e.g. writing to Cloud Firestore or sending a Pub/Sub message
Michael Bleigh
  • 25,334
  • 2
  • 79
  • 85
  • Thanks for your reply Michael, I was thinking, it's possible to have a second endpoint to do that work for me ? Something like, receive the slack dialog data, call another endpoint to do everything I need (but without waiting for the response) and then call `res.send()` ? – Lucas Andrade Oct 03 '19 at 14:55
  • 1
    That might work, the only problem would be you'd have to wait long enough to make sure the second request has actually started processing before `res.send()` (network is clamped in addition to CPU etc. as soon as the response is sent). You might be able to do this reliably with a timeout, but using Pub/Sub or another background function will be a more surefire reliable solution. – Michael Bleigh Oct 03 '19 at 16:00
  • @MichaelBleigh I want to write to PubSub after calling `res.send()`. Do i have to wait for the PubSub message to be succesfully sent (waiting for the promise to resolve), before calling `res.send()`? – Eric Guan Jun 29 '20 at 22:47
  • Yes, you need to wait for the PubSub message to be sent before calling `res.send()` -- you can't count on *anything* executing for sure after the response has ended. – Michael Bleigh Jun 30 '20 at 16:20