Hi,
In our system there are web (browser) users and native mobile app users. Both connect to a Presence channel and are tracked fine when they join and leave the channel. We’d like to separate the online
state, which is when the client is connected to the presence channel, from the reachable
state, which is when a mobile client is not connected to the channel, but has a valid login session and is reachable via push notifications. That is, when the device is not being used or the app is closed. Our presence meta
has to carry that state, e.g.:
{:ok, _} = Presence.track(socket, socket.assigns.current_user.id, %{
online_at: System.os_time(:second) |> to_string(),
agent_type: socket.assigns.session.agent_type,
status: :online,
client_ref: "some_ref"
})
One approach we tried to explore was to update the :online
status with e.g. :reachable
on an existing meta. When the client reconnects we’d have to find that meta by its client_ref
and update the status back to :online
. That’s where we met a number of challenges which makes us wonder whether we’re doing something wrong.
Simply put, we didn’t find a way to update an existing meta when the client disconnects, because by the time the presence_diff
is intercepted, the presence state has already been updated and the meta in question has been deleted.
It only remains possible to track a new meta in place of the deleted one. This is fine, but then we have to allow two diff
events broadcast, one with leaves
and one with joins
, referring to the same client, and that’s undesirable.
One possible solution would be to implement a custom Tracker with its handle_diff/2
which would manipulate the state before sending out a single broadcast. Yet, maybe we are missing something conceptually and the whole approach needs to be changed. How would you do this?