Open ndrean opened 1 year ago
Sidenote (not from me)
PubSub: allow processes to communicate with each other between a node or multiple nodes. This is important in a distributed world, where server A has a message for a user that’s connected to server B. The message is dispatched over PubSub and the process on server B picks it up for delivery to the user.
Tracker: Tracker is a CRDT-based library to keep a list of information in-sync across a cluster. This information could really be anything, although it’s commonly something related to connected users or other ephemeral types of information. When you write an implementation for Tracker, you have to provide some callbacks like handle_diff 14.
Presence: Implementation of Tracker that works out of the box with Phoenix Channels. You don’t really have to do anything for this other than tie your channels to a Presence module—it’s all built for you already. There is also some JS provided by Phoenix framework for handling Presence on the frontend as well.
Presence is really well suited when you want the list of presence information to be sent to your clients. The quintessential example of this is “who’s online in this chat room” type of information. If you don’t want to broadcast the presence information to clients, then Tracker may be better because you will avoid doing excess work (costs CPU) that you don’t need to do.
PubSub is really separate here. It enables communication, but it doesn’t do anything regarding keeping stateful information distributed in your cluster. It’s not as easy as “broadcast a message that someone joined the channel” because distributed systems introduce a whole host of problems (what happens if a server disconnects, there is a networking issue, etc). Tracker (and therefore Presence) is designed to work in these real-world conditions.
A drawing is easier to follow I believe: set up N(N+1)/2 one-to-one channels (subscriptions) between users. You need to monitor subscriptions, meaning unsubscribe on deconnection, otherwise you have multiple rendering.
The idea is when a user mounts, he "pre"-build N-1 channels with every connected user, and the topic follows the convention #{user_id}-#{another_user_id}"
.
This way, we have N-1 one-to-one connections. A user can now push a notification to another user and send a private message.
Tested with 3 users (thanks to Dwyl's excellent login tools)
However, I wanted to be able to check the existing subscriptions.
Edit 1: you can indeed get all the topics a user subscribed to with:
Registry.keys(MyApp.PubSub, self())
(the error was MyAppWeb.Pubsub instead of MyApp.PubSub .... ^^)
Edit2: I learnt that you can't pattern match on an empty map. Use guard clause Example: to get get "leaves" events, do:
def handle_info(%{event: "presence", payload: %{joins: joins}, socket) when joins == %{}
Question: How do you create a private chat between two users?
When you look at the code for Phoenix.PubSub.subscribe:
Dwyl/I use
Phoenix.Endpoint
instead ofPhoenix.PubSub
and the PubSub is started with:and the standard configuration is:
We don't use the "atom" form" . Does this start a registry?
I don't see anything: