udia v0.1.1 Udia.Web.Presence

Provides presence tracking to channels and processes.

See the Phoenix.Presence docs for more details.

Usage

Presences can be tracked in your channel after joining:

defmodule Udia.MyChannel do
  use Udia.Web, :channel
  alias Udia.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
    push socket, "presence_state", Presence.list(socket)
    {:ok, _} = Presence.track(socket, socket.assigns.user_id, %{
      online_at: inspect(System.system_time(:seconds))
    })
    {:noreply, socket}
  end
end

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 list for the socket’s topic is pushed to the client as a "presence_state" event.

Finally, a diff of presence join and leave events will be sent to the client as they happen in real-time with the “presence_diff” event. See Phoenix.Presence.list/2 for details on the presence datastructure.

Fetching Presence Information

The fetch/2 callback is triggered when using list/1 and serves as a mechanism to fetch presence information a single time, before broadcasting the information to all channel subscribers. This prevents N query problems and gives you a single place to group isolated data fetching to extend presence metadata.

The function receives a topic and map of presences and must return a map of data matching the Presence datastructure:

%{"123" => %{metas: [%{status: "away", phx_ref: ...}],
  "456" => %{metas: [%{status: "online", phx_ref: ...}]}

The :metas key must be kept, but you can extend the map of information to include any additional information. For example:

def fetch(_topic, entries) do
  query =
    from u in User,
      where: u.id in ^Map.keys(entries),
      select: {u.id, u}

  users = query |> Repo.all |> Enum.into(%{})

  for {key, %{metas: metas}} <- entries, into: %{} do
    {key, %{metas: metas, user: users[key]}}
  end
end

The function above fetches all users from the database who have registered presences for the given topic. The fetched information is then extended with a :user key of the user’s information, while maintaining the required :metas field from the original presence data.

Summary

Functions

fetch(topic, presences)

Callback implementation for Phoenix.Presence.fetch/2.

handle_diff(diff, state)

Callback implementation for Phoenix.Presence.handle_diff/2.

init(opts)

Callback implementation for Phoenix.Presence.init/1.

list(topic)

Callback implementation for Phoenix.Presence.list/1.

start_link(opts \\ [])

Callback implementation for Phoenix.Presence.start_link/1.

track(socket, key, meta)

Callback implementation for Phoenix.Presence.track/3.

track(pid, topic, key, meta)

Callback implementation for Phoenix.Presence.track/4.

untrack(socket, key)

Callback implementation for Phoenix.Presence.untrack/2.

untrack(pid, topic, key)

Callback implementation for Phoenix.Presence.untrack/3.

update(socket, key, meta)

Callback implementation for Phoenix.Presence.update/3.

update(pid, topic, key, meta)

Callback implementation for Phoenix.Presence.update/4.