defmodule MyAppWeb.MyChannel do
use MyAppWeb, :channel
alias MyAppWeb.Presence
def join("some:topic", _params, socket) do
send(self(), :after_join)
{:ok, assign(socket, :user_id, ...)}
end
def handle_info(:after_join, socket) do
{:ok, _} = Presence.track(socket, socket.assigns.user_id, %{
online_at: inspect(System.system_time(:second))
})
push(socket, "presence_state", Presence.list(socket))
{:noreply, socket}
end
end
it pushes to presence_state on :after_join event…
after that how does it work? how state is being pushed down to client in realtime as changes are happening?
is there any good way to hook into presence_state to identify which clients are online realtime?(I want to implement a total user counter)
In the example above, Presence.track is used to register this channel’s process as a presence for the socket’s user ID, with a map of metadata. Next, the current presence information for the socket’s topic is pushed to the client as a "presence_state" event.
Emphasis above added by me. As you call Presence.track/3, it will associate the calling process with this specific user_id, and then when the process goes away (ie: the channel of the example is closed, or in other spaces the LiveView process is ended) the “presence” of this user_id is considered lost.
You might get value from this blog post, which talks about Presence at the end:
Nope. It gets the pid of the calling process and then uses Phoenix.Tracker and other things inside Presence to observe the life of the process via standard BEAM features.