Users Presence Monitoring Using Firebase Realtime DB Rest API

266 Views Asked by At

I am building a chat application with an online/offline feature, using firebase rest API as my backend (without JS SDK).

First I try to implement a solution on the client-side only:

  1. Detect that the user disconnected (leave the site)
  2. Update a dedicated path in the RealTime DB - (/userStatus/{userId}/{online||offline})

Similar to the next tutorial: https://firebase.google.com/docs/firestore/solutions/presence

But it didn't work.. the WebSocket onClose or window.onbeforeunload events didn't catch all scenarios.

Second I try to build a server-side solution that checks when the Firebase Websocket is a life. but I didn't find any clue on how to achieve that.

So I come up with the last brute-force solution:

  1. update the online endPoint every minute with the last userConnectionTime
  2. Users with lastConnectionTime < now - 1 minute = disconnected.

But this solution means that I need to update the Db every minute for all users, and each user needs to listen to all of his contacts and will receive every minute an irrelevant message with the lastConnectedTime.

This solution is not ideal... My question is does anyone have another better one? Thank you

2

There are 2 best solutions below

2
Frank van Puffelen On

When using Firebase's onDisconnect handlers, there are two types of disconnects:

  • Clean disconnects, where the client informs the server that it is about to disconnect. In this scenario, the server executes the onDisconnect handlers straight away.
  • Dirty disconnects, where the client (from the server's perspective) simply disappears (e.g. due to a crash, a broken carrier connection, or many other cases). In this scenario, the server executes the onDisconnect handlers when the socket times out (typically after a few minutes).

It sounds like your first approach should have worked, and is in fact the simplest way to do this as Firebase takes care of most of the hard work for you. Firebase has an onunload handler that on most cases can do a clean disconnect, but even when it can't - the server should run the onDisconnect handlers when it detects that the client is gone.

If you're having trouble making this work, I recommend posting a minimal reproduction of the problem so we can help you troubleshoot.

0
dan On

After a little of reverse engineering I found two things:

  1. calling onDisconnect send a unique message to the server, with an "action". In the case of dirty disconnects the action will accord on the server side (awesome!)

  2. The .ref('.info/connected').on('value'... probably happen in the client side only, and probably listen on socket.onClose and window.onbeforeunload events and close the connection gracefully but not reliably.

The message the JS-SDk send when calling the onDisconnet:

  {
        "t": "d", // type: d-data, c-info...
        "d": { 
            "r": 2,   // index
            "a": "o", // actions: o=onDisconnect, q=query...
            "b": {   
                "p": "/onlineUsers/{userId}",  // path
                "d": "true" // data
            }
        }
    }