Understanding Phoenix Presence

i dont understand how phoenix presence works

in the examples

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)

PS: Im following this for my usecase Phoenix Presence for social networks | by Alvin Lindstam | Medium

From the docs, right under the sample you shared:

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:

https://elixirschool.com/blog/live-view-with-presence

Good luck!

5 Likes

Thanks for the explanation, does it means Presence injects some behaviour into the channel to do this?

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.