Firebase Cloud Function Realtime Database Trigger - firebase

are the realtime database trigger onWrite onCreate queued or threaded ?

Neither.
Cloud Functions events don't necessarily get handled in the same order that they occurred. If you are depending on ordering, your functions may not work the way you expect. There is no single ordered queue that all events pass through - this would not scale.
Each function invocation runs full isolation from other function invocations. Cloud Functions will spin up new server instances to handle load as needed. So, if one server is busy handling events, Cloud Functions may decide to add more servers to the mix to be able to handle more incoming events. Each server handles only one event at a time. The events are handled serially within each server instance, and handled in parallel between server instances. There is no "threading" going on, from the perspective of the event trigger code (that's not the way node.js works for application code).

Related

What happens when I use .on() in Firebase Cloud Functions?

If I do not use .off() in particular to shut down the event listener, will it be turned off automatically when the http request has been processed?
So when a user browses http://www.example.com/organisations and I retrieve the data with an .on() call like:
admin.database().ref('organisations').on('child_added', snap...)
What happens with that connection when the request is done and the user got his data? Since I don't close the event listener with .off() I should assume Cloud Functions is still listening to the child_added event? But on the other hand that wouldn't make any sense for an http-request, so I could also assume that Firebase closes all event listeners after the request has been processed?
If you don't call off() to stop a listener that was started by on(), it will not turn off. You may be billed for the bandwidth it consumes until the allocated server instance shuts down.
Use of on() in Cloud Functions is almost never the right thing to do.
You should probably just be calling once() at the location of your data and use it when it's ready.

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.

With Meteor, how to I run a singleton that updates periodically while clients are connected?

I'm just getting started with Meteor and I have a REST API hooked up with publish / subscribe that can periodically update per client. How do I run this behavior once globally and only refresh as long as a client is connected?
My first use case is periodically refreshing content while clients are active. My second use case is having some kind of global lock to make sure a task is only happening once at a time. I'm trying to use Meteor to make a deployment UI and I only want 1 deployment to happen at once.
publish/subscribe will work automatically only when clients are connected. However, do not put any functionality that you want to control amount of execution times in publish or subscribe functions. They might run arbitrary amount of times.
If you want some command to be executed by any client use Meteor.methodss on server side, and call it explicitly with Meteor.call from client template event.
To make sure that only one deployment happens at any given time, simplest way would be to create another collection, called for example, CurrentDeployments.And any time deployment script function in Meteor.methods is executed, check with CurrentDeployments.findOne if there are ongoing deployment or not, and only call new one if none is running.
As a side bonus, subscribe to CurrentDeployments in client, to disable 'deploy' button in case one is already running.

Do local db writes happen synchronously or asynchronously?

New to firebase and trying to understand how things work. I have an android app and plan to use the offline support and I'm trying to figure out whether or not I need to use callbacks. When I make a call like:
productNode.child("price").setValue(product.price)
Does that call to setValue happen synchronously on the main thread and the sync to the cloud happens asynchronously? Or does both execute asynchronously on a background thread?
The Firebase client immediately updates its local copy of the data with the new value. As part of this it fires any local (value, child_*) events that are needed.
Sending of the data to the database happens on a separate thread. If you want to know when this has completed, you can register a CompletionListener.
If the server somehow cannot complete the write operation (typically because the write violates a security rule), the client will fire any additional events that are needed to get the app back into the correct state. So in the case of a value listener it will then fire a second value event with the previous value.

how to build a presence system with the new firebase queue

I have a chat application using firebase and node.js where I keep track of presence by running a single worker thread on the server that monitors child_added and child_deleted events on the firebase presence channel, and updating our presence database tables accordingly.
My question is this - now that firebase queue exists https://www.firebase.com/blog/2015-05-15-introducing-firebase-queue.html
Can I use the queue to replace the worker thread that I have running on the server to monitor presence and child_added events? Looking at the current examples - it looks like I would create a reference to the queue on the client and then set on disconnect and connect events to push into that queue from the client? However I'd like to secure it a bit more and not rely on the client so much. I'd also like to have the queue process the event by archiving it to a 3rd party logging service - credentials or details I wouldn't want to expose to the client.
Does this mean I would still need a server side worker process - and if so what benefit would the firebase queue be in this use case?
Firebase Queue is not a hosted solution - you still need to run it on your own server.
The main advantage of using a queue over a single listener process is the ability to run multiple workers for the same tasks so there's not a single point of failure. Using the queue you'll know that the worker processes are synchronized such that only one worker will be processing a task at any one point in time, and if a worker dies during processing or takes too long, another worker will pick it up again once the task has timed out.
It sounds like you're trying to create some kind of audit trail for presence, but there's currently no way to report presence directly from the server - you'll need to rely on the client at some point. Your security rules can enforce whether a write is a boolean to specific location in your database, but they can't enforce that the client was in any particular presence state when writing it. Also note that there's no push or childByAutoId equivalent onDisconnect handler, so to push to a queue you'd have to do something like:
var ref = new Firebase(…);
var disconnectTask = {};
var pushId = ref.push().key(); // This just generates the ID and does no network traffic
disconnectTask[pushId] = { /* populate with task data here */ };
ref.onDisconnect().update(disconnectTask);
Note that the push ID will be generated client-side before the operation is sent to the server and so the task won't necessarily be in order when added to the queue.

Resources