firebase HTTP function termination - firebase

Is it OK practice to put additional logic into a Firebase HTTPS function, after the response was sent?
I have functions where this is happening:
write to the Firebase DB
once the write is done, I send back the response (this is where res.status(200 / 500).send() is
called)
I look up some FCM tokens in the DB and send a push message (it does not matter from a requester perspective if this is successful or not)
I understand that another pattern could be that I move step 3 to another DB trigger function to do the messaging. That would introduce some delay as I'd need to wait for that DB trigger function to fire.
My question is: is it safe to put additional logic to a HTTPS function after the
response is sent, or Firebase may start to cleanup / terminate my function already?

firebaser here
While your sending of FCM messages (in step 3) may frequently work, it is not reliable. There is no guarantee that the HTTP-triggered function will continue running after a response has been sent.
Precisely for this reason the Firebase documentation says:
HTTP functions are synchronous, so you should send a response as quickly as possible and defer work using Cloud Firestore.
So in your case, the documentation explicitly says to put the sending of the notification into a database-triggered function.

Related

Trace request as it propagates through Google Cloud Functions

Say you have an HTTP endpoint which, when triggered, publishes a PubSub message and then sends a response.
There is another Cloud Functions which is subscribed to this event, performs what it needs to perform, and then ends.
How would you go about to trace the entire sequence of function executions triggered by an initial request (in this example, the first HTTP request)?
I see in the Google Cloud Platform logs there is a function Execution ID, but this changes with each function that is triggered hence it's hard to follow the sequence of executions. Is there an automated way of doing this? Or does it need custom implementation?
Thanks!
You will need a custom solution. If you want to trace this all the way back to the client request, you will need to generate some unique ID on the client, and pass that along to the HTTP function, which would then pass that along to the pubsub function via the message payload. And so on.
You might find it helpful to use StackDriver logging to collect the logs around that unique ID.

Idempotency in Google Cloud Function HTTPS triggers

Most firebase cloud function trigger function signatures include a context object which has an eventId property.
Looking at the documentation, this doesn't seem to be the case for HTTPS-triggers.
Is it safe to assume that calls to HTTP functions will only trigger once per request?
Jack's answer is mostly correct, but I'll clarify here.
The documentation on execution semantics is here. To be clear:
HTTP functions are invoked at most once. This is because of the
synchronous nature of HTTP calls, and it means that any error on
handling function invocation will be returned without retrying. The
caller of an HTTP function is expected to handle the errors and retry
if needed.
There is no guarantee that an HTTP function is executed exactly once. Some executions may fail before they reach the function. This is different from all other (background) types of function that provider at least once execution:
Background functions are invoked at least once. This is because of
asynchronous nature of handling events, in which there is no caller
that waits for the response and could retry on error. An emitted event
invokes the function with potential retries on failure (if requested
on function deployment) and sporadic duplicate invocations for other
reasons (even if retries on failure were not requested).
So, for background functions to be 100% correct, they should be idempotent.
If you want to retry failed HTTP functions, the client will have to perform the retry, and in that case, you may want that HTTP function to be idempotent as well. The client will have to provide the unique key on retry, in that case.
Note that it's not possible to mark an HTTP function for internal retries. That's only possible for background functions.
HTTPS functions will only trigger once compared to background functions that have a at least once delivery guarantee.
(I cant find the docs where I read it. If I find it i will update the question)

Stop a firebase function from retrying on timeout?

Is it possible to stop a Firebase Cloud Function from retrying if it times out?
It looks like it is possible to config the retry logic of Google Cloud Functions. But I can't find that setting anywhere when using Firebase functions.
The functions that are doing this are triggered with:
exports.myFunction = functions.https.onRequest((req, res) => {
...
});
The function is sending a POST request to an outside service that has a tendency to hang, even when the operation was successful.
When this happens I see logs for the function execution starting, then timing out, then immediately starting again. What is causing this retry? And can I stop it from retrying?
This is about HTTP Protocol. Also retry configuration is not applicable for Http triggered cloud functions.
When a cloud function terminates due to timeout, it basically returns a 408: Request Time-out response. If your browser support 408 HTTP Protocol, it will resend the request to cloud function. I am not sure but Chrome does this while Safari doesn't.
I am also suffering from this strange behavior of Firebase functions(sending 408 on timeout). I think only way to fix this is to create a wrapper on your function which returns a response just before function times out. I am trying to create one but couldn't have done it yet.
Retries are off by default.
You can configure your function in the Cloud console.

Firebase - handle errors on cloud function trigger

I am starting to use Firebase Cloud function and it is generally great.
The only thing that is not clear to me is how to handle a failure of the process that runs in the trigger function.
For example - I have a trigger on Firebase Auth that creates a Stripe Customer on our Stripe account every time a new user is created.
It is possible that the Stipe API call will fail. In a "Normal" HTTP request I will return an error to the client that will respond accordingly, but on a cloud function I do not have a callback from the trigger (Or do I?)
Any Idea how to handle this while using cloud function?
Thanks
What you do in an auth trigger depends on the APIs you're calling. As you know, in HTTP functions, you return a response to the client for every code path that can occur. For all other types of functions (including Auth functions), you need to return a promise that becomes resolved when all the work is complete. If the Stripe API uses promises, you can simply use those (in addition to any others in your code) to return a single promise. If you have a promise in hand, you can know if its work fails by using catch() on that promise to trap the error.
I strongly recommend reading the Firebase docs on promises, and also looking at sample code (especially the Stripe example).

Trigger a Cloud Function and take action when function completes

I have an application where the web ui (react) Cloud Function then runs and updates a completion value in the database.
How can I show a 'progress' indication and take it down when the Cloud Function has completed?
I initially thought I would do something like this pseudo code with Promises:
return updateDatabaseToTriggerFunctionExec()
.then listenForFunctionDoneEvent()
.then return Promise.resolve();
However, I'm not sure how to know when the function has finished and updated a value. What is the recommended way to detect when a triggered Cloud Function has completed?
You'll have to implement something like a command-response model using the database as a relay where you push commands into a location and the function pushes results out that can be listened to by the client that issued the command. The thing that makes this work is the fact that the locations of the commands and responses and known between the client and server, and they have a common knowledge of the push id that was generated for the client command.
I go over this architecture a bit during my session at Google I/O 2017 where I build a turn-based game with Firebase.
An alternative is to use a HTTP function instead, which has a more clearly-defined request-response cycle.

Resources