Using node server to listen to changes .on('value') to trigger a system event, eg. send email

500 views
Skip to first unread message

Olivier Mills

unread,
Jul 25, 2015, 11:20:29 PM7/25/15
to Firebase Google Group
I would like to use node server to listen to changes .on('value') to trigger a system event, eg. send email.

Is this an ok approach? Having a node server with full auth, continuously listening for changes at a specific path in FB, then triggering some event. This is to avoid the trigger happening on the client side? If not a good idea, what other approaches are recommended?

Here is an example:

Client side:
User creates a new booking  /bookings/[newid]

Server side:
ref = ref('.../bookings')
ref = .on('value', function() {
  sendemail();
});

Thanks!

Olivier

Frank van Puffelen

unread,
Jul 26, 2015, 10:13:18 AM7/26/15
to Firebase Google Group, oli...@millsitconsulting.com
Hi Olivier,

Having a node server listening for changes is a quite common way to extend Firebase functionality.

The only concern I'd have with your approach is that you might miss intermediate values if the node server is down.
  1. Node script starts listening
  2. A user changes the value to 1
  3. Node script receives event and sends email 1
  4. A user changes the value to 2
  5. Node script receives event and sends email 2
  6. Node script dies
  7. A user changes the value to 3
  8. A user changes the value to 4
  9. A user changes the value to 5
  10. Node script is started again and starts listening
  11. Node script receives event and sends email 5
In the above scenario, emails 3 and 4 will never be sent. The reason for this is that Firebase will not synchronize the intermediate value changes when the node server reconnects in step 10. Firebase synchronizes state ("the value is 5"), it does not synchronize state changes ("a user changed the value from 4 to 5").

If handling all state changes is required for your use-case, it is better to model the state changes in your database. A simple example of this is when you're trying to keep a counter between multiple clients (always a tricky situation in a distributed system like Firebase). The common method is to store a count in Firebase and then have each client update that value.

    /count: 1

    ref.child('count').transaction(function(count) {
      return (count || 0) + 1;
    });

If multiple clients run this code, they're all updating the same location. Not only does that lead to contention, it also leads to the scenario we had before where listeners may not see every update. 

The alternative is to not store the count, but the "increments" themselves as a separate action. In that case, the clients would push increments onto a queue:

    /increments

    ref.child('increments').push(1);

With this model you guarantee that each increment becomes a separate record in the database, so every listener is guaranteed to see each increment. As a nice bonus, this approach also removes the lock contention.

This last approach is used extensively in Firebase's internal processes. We often use firebase-queue to implement the server-side processes.

Michael Lehenbauer

unread,
Jul 27, 2015, 11:53:01 AM7/27/15
to fireba...@googlegroups.com, oli...@millsitconsulting.com
Hey Olivier,

Your initial approach may be fine since it looks like each client will be writing under a new /bookings/[newid] location.  That means that even if the server is offline for a while, all of the bookings will still be there when the server comes back online.

My new concerns would be that:
  1. It's not clear if/when the /bookings/ entries will be removed.  If they just continue to build up, the location will get larger and larger and your app will slow down.
  2. Again, if you're not removing /bookings/ entries, your server has to somehow keep track of which bookings it has already seen (and sent an email for) and which ones are new.
  3. In general, the 'child_added' event may be more convenient to use than 'value' since it'll fire once with each child.  'value' will fire with *all* of the /bookings/ data, so you'll have to examine all of them in your event handler to find the new one(s).
As Frank mentioned, firebase-queue is a great option for handling these sorts of server-side tasks.

Best regards,
-Michael

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/95295976-6795-4e2f-b49c-241a6fc4b828%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages