I am using Firebase's cloud functions to execute triggers when a client adds something to the database, but it seems like these triggers take long time to execute.
For example, I have a trigger that adds a creation date to a post whenever a post is added to the database, and it takes like 10 seconds to complete.
Also, I have larger triggers that take even longer.
Is there like a "best practice" I am missing? Am I doing anything wrong?
I've found that the reason that Cloud Functions sometimes takes time to respond, is because they have a "warm up" period, meaning that the first time you call a cloud function it begins to warm up, and it won't be fully responsive until it is warm.
After it warms up, it will be as responsive as you would expect.
The reason for this behavior is resource resource balancing - If you don't use a function for some time, it will shut down and clear resources so other functions will be more responsive.
Related
Apparently some of onCreate/onDelete events our cloud function is triggered by are received more than once!
We've observed them arriving even 3 times a few seconds apart from each other spread between instances of the cloud function. Is it a normal behavior or there is something we've been doing wrong?
Have a look at the content of this "Firebase Google Group" post, that I paste below. It was written in August 2018 but is still fully valid at the time of writing this "copy/paste answer".
Cloud Functions typically
guarantees that your functions are run "at least once", meaning that
it's very possible (but typically rare) that an event may get
delivered to your function more than once. To deal with this, your
functions should be "idempotent", meaning that the receipt of the same
event multiple times should result in no further changes to whatever
it is you need to update. This can be kind of challenging, but it's
one of the properties of serverless systems that needs to be dealt
with, if it's problematic for your app.
https://cloud.google.com/functions/docs/bestpractices/tips#write_idempotent_functions
I'm writing a small game for Android in Unity. Basically the person have to guess whats on the photo. Now my boss wants me to add an additional function-> after successful/unsuccessful guess the player will get the panel to rate the photo (basically like or dislike), because we want to track which photos are not good/remove the photos after a couple of successful guesses.
My understanding is that if we want to add +1 to the variable in Firebase first I have to make the call and get it then we have to make a separate call with adding 1 to the value we got. I was wandering if there is a more efficient way to do it?
Thanks for any suggestions!
Instead of requesting firebase when you want to add ,you can request firebase in the beginning (onCreate like method) and save the object and then use it when you want to update it.
thanks
Well, one thing you can do is to store your data temporarily in some object, but NOT send it to Firebase right away. Instead, you can send the data to Firebase in times when the app/game is about to get paused/minimized; hence, reducing potential lags and increasing player satisfaction. OnApplicationPause(bool) is one of such functions that gets called when the game is minimized.
To do what you want, I would recommend using a Transaction instead of just doing a SetValueAsync. This lets you change values in your large shared database atomically, by first running your transaction against the local cache and later against the server data if it differs (see this question/answer).
This gets into some larger interesting bits of the Firebase Unity plugin. Reads/writes will run against your local cache, so you can do things like attach a listener to the "likes" node of a picture. As your cache syncs online and your transaction runs, this callback will be asynchronously triggered letting you keep the value up to date without worrying about syncing during app launch/shutdown/doing your own caching logic. This also means that generally, you don't have to worry too much about your online/offline state throughout your game.
So according to the Google Cloud docs:
Max inactivity time for background functions = 30 days
The maximum amount of time that a background function can be kept without any invocation. Functions that are not invoked even once during this time may enter a state in which new events will not trigger them anymore. If this happens, such functions have to be redeployed to start working again. Note: This inactive state is not reflected in the UI, CLI, or API in any way.
I have an application with close to 40 cloud functions and there doesn't seem to be an easy way for me to tell if a function is close to becoming inactive so I know to take action before it happens and I really don't want to filter through the logs in the console with each function every week to see when each was invoked last.
Outside of just doing a redeploy of my functions every month to insure they are fresh is there anyway to easily tell when a function is becoming stale in case it does happen so I only have to deploy said function before it becomes stale?
Also, for any firebase'r that might read this, is there any solutions possibly coming to this in the future?
Thanks in advance.
Sorry, there's no way to tell where your function is during its 30 day idle expiration. The good news is that the Cloud Functions team is working on removing this limitation, but there's no public timeline for that.
EDIT: This problem is resolved now for all newly deployed functions.
I tried a couple of my trigger functions as https.onCall and called them after promise return and so far they work really well and faster than the triggers.
What's the catch? Are they also affected by the cold starts too?
If not, then unless it's cron job or lack of support of app language, why should anyone use use a trigger function at all?
All Cloud Functions are affected by cold starts. This is how all serverless function architectures work. In order to scale down to zero (so you pay nothing if you use nothing), all server instances must be able to be decommissioned. Cold start up cost is paid when a new server instance is allocated, so going from zero to one will cost you one cold start.
You haven't defined what a "trigger function" is, so I'll assume you mean a "background function" which triggers in response to events that occur within your project.
Background functions are absolutely required when you want to have some work performed in response to those changes when you can't trust the client to perform that work directly. This is important to maintain data consistency, and also to prevent having to duplicate logic among all your different clients that are all doing the same thing. This also allows you to ship new features and bug fixes without having to ship new client code, which can be difficult and time-consuming.
After watching a fair amount of youtube videos, it seems that Google is advocating for multipath updates when changing data stored in multiple places, however, The more I've messed with cloud functions, it seems like they're and even more viable option as they can just sit in the back and listen for changes to a specific reference and push changes as needed to the other references in real time. Is there a con to going this route? Just curious as to why Google doesn't recommend them for this use case.
NEWER UPDATE: Literally as I was writing this, I received a response from Google regarding my issues. It's too late to turn our apps direction around at this point but it may be useful for someone else.
If your function doesn't return a value, then the server doesn't know how long to wait before giving up and terminating it. I'd wager a quick guess that this might be why the DB calls aren't getting invoked.
Note that since DatabaseReference.set() returns a promise, you can simply return that if you want.
Also, you may want to add a .catch() and log the output to verify the set() op isn't failing.
~firebase-support#google.com
UPDATE: My experience with cloud functions in the last month or so has been sort of a love-hate. A lot of our denormalized data relied on Cloud Functions to keep everything in sync. Unfortunately (and this was a bad idea from the start) we were dealing with transactional/money data and storing that in multiple areas was uncomfortable. When we started having issues with Cloud Functions, i.e. the execution of them on a DB listener was not 100% reliable, we knew that Firebase would not work at least for our transaction data.
Overall the concept is awesome. They work amazingly well when they trigger, but due to some inconsistencies in triggering the functions, they weren't reliable enough for our use case.
We're currently using SQL for our transactional data, and then store user data and other objects that need to be maintained real-time in Firebase. So far that's working pretty well for us.