gohttpasynchronousgoogle-cloud-platformgoogle-cloud-functions

Pattern for handling deferred tasks in a GCP Cloud Function


My problem is almost identical (though not quite, as Flusher doesn't work) to How to send response to the client before executing the calculations that are not required in response

I have a Go-based HTTP handler Cloud Function that receives some data from a device and then sends back a set of configuration data. Speed is a priority and seconds occasionally matter. Constructing the response is very quick (it's just a DB pull). Separately, the received data needs to be processed which can take on the order of ~5 minutes. I tried the pattern in the linked question and the client doesn't receive the data until the cloud function exits. The http.Flusher interface suggests "Note that even for ResponseWriters that support Flush, if the client is connected through an HTTP proxy, the buffered data may not reach the client until the response completes." so I assume that's the problem.

Is there an alternative way to invoke an HTTP Cloud Function, return a response, and then keep the function live while the waitgroup does its thing? Can I force close the connection to tell the (assumed) proxy to get on with it?

On a normal server, I'd just defer it outside of the handler and not bother waiting, but since the runner dies when it exits, that's not an option. My other thought is maybe shipping the data off to pubsub and having a separate function do the processing, but that seems wasteful and adds another point of failure.


Solution

  • Is there an alternative way to invoke an HTTP Cloud Function, return a response, and then keep the function live while the waitgroup does its thing?

    No, that's not how Cloud Functions works with any language or runtime. If you want to continue processing after a response is sent, you must push that work into a second processing unit, which is either a second function invocation, or some other compute product that you can access via some API.

    Can I force close the connection to tell the (assumed) proxy to get on with it?

    No, there is no "connection" from the point of view of the function, just inputs and outputs. Cloud Functions will only send the final response after the entire payload of the response has been generated by the function. That's why the documentation states a limit of 10MB in size.

    My other thought is maybe shipping the data off to pubsub and having a separate function do the processing, but that seems wasteful and adds another point of failure.

    That's actually precisely what you should do. This has been covered in the past: