Presence/Tracker track user metada without pid

Hello all

I’m building a websocket server application with phoenix, and I manage to follow the tutorials to code it and deploy id in a multi nodes cluster. I a want more than just a chat room.
I’d like to keep a state for each user connected, so I tested Presence and it work well for keeping info for each connected socket.
Bu I would like the state to depend on user_id and not by socket, and to continue to live after the user is disconnected.

SO I’m confuse if Presence is the good tool, or even Tracker, since they are linked to the Channels to automatically remove the socket info when deconnected. This mandatory ‘pid’ is bothering me … I wonder if I could track another process to keep only one metadata by user_id key ? If yes what could be a good candidate.
I wonder also if Presence is too much for this. Maybe a simple GenServer might suffice (since I’m not interested of the broacasting feature to the client), but I understand the Tracker state is distributed amongth the node thank to PubSub.

So, do you have any advice to use Presence/Tracker without the mandatory ‘pid’ ?

So a database then? :slight_smile:

That’s the point of them, they track the Liveness of a connection, whatever you do with that connection is all up to you. :slight_smile:

1 Like

hello @OvermindDL1
Thank you for your answer.
I’m afraid you right about using something else …
I hopped to use the distributed aspect of the Tracker without the POF of a database.

Maybe directly using PubSub to distibute the state over the node ?

1 Like

Can you expand on your goal more? What are you looking to do with the state once you have it?

@OvermindDL1 is correct that Tracker is linked to the idea of tracking processes. If the process goes down, it is counted as a leave. You may be able to use something like GitHub - derekkraan/delta_crdt_ex: Use DeltaCrdt to build distributed applications in Elixir to have a CRDT that isn’t tied to processes.

Here is a blog post I wrote when looking to implement a distributed cache.

2 Likes

hello @sb8244

I’m building a chat room where an ‘admin’ user can set a status for other users… and depending of this status the user can do some action of not.
I first tried to use the Presence on the user socket connections, but as soon as he is disconnected, the status disappeared (logic).
And the status is dependent of the admin(s) connection as well … so I was going to move the status management by a Presence on user to a Presence on admin(s) … but still the status is too much directly dependent of the connection of the admin(s).
It happen that this status should not be persisted infinitely. If the admin reconnect after a few day, the status can be deleted… That why I doesn’t look for something as solid as a database.

I read your article, that I found very inspiring - as I discover pg2 (I forgot to tell that this is my very first Elixir project) … I will try simply using it, It might suffice.
Thank you again

1 Like

I might suggest the database in this case. It sounds like you’re battling against the state being ephemeral when you want it to be more permanent.

Using postgres or Redis could give you the persistence you want. You won’t have to battle against the fact that connections come and go, or servers redeploying.

One technique that could work to maintain performance is to have a user channel request the current state of itself from the database when it joins. When the admin changes the value, you could write it to the database and use pubsub to broadcast it to all nodes (pubsub uses pg2 under the hood, or Redis if you can’t get node networking to work).

Hello all
just to close the subject, this is roughtly the solution I’m working on :
onjoin on the channel, a process is created that is linked to the channel, and listent when the channel is exited.
When exited the process kill itself after the ttl, and this is this process PID that is monitor in the same way the tracker works.
But instead of the tracker I develop something inspired of your distributed cache @sb8244 … but instead of :pg2, I used Phoenix.PubSub to communicate between node.

Thank you again for you help

1 Like