Using Elixir as a Presence Client

I’m trying to follow the documentation on using Elixir as a Presence Client as outlined here: [Phoenix.Presence — Phoenix v1.7.14]

Channel join code :

@impl true
  def join("online", params, socket) do
    IO.inspect(params, label: "PARAMS on join")
    send(self(), :after_join)
    {:ok, socket}
  end
  @impl true
  def handle_info(:after_join, socket) do

    IO.inspect(socket)
    user_id = socket.assigns.user
    {:ok, _} = Presence.track(socket, user_id, %{
      user_id: user_id,
      online_at: inspect(System.system_time(:second))
    })
    push(socket, "presence_state", Presence.list(socket))
    {:noreply, socket}
  end



Code for presence.ex



    def init(_opts) do
      {:ok, %{}} # user-land state
    end

    def handle_metas(topic, %{joins: joins, leaves: leaves}, presences, state) do

      IO.inspect(joins, label: "JOINS")
      # fetch existing presence information for the joined users and broadcast the
      # event to all subscribers
      for {user_id, presence} <- joins do
        user_data = %{user: presence.user, metas: Map.fetch!(presences, user_id)}
        msg = {MyApp.PresenceClient, {:join, user_data}}
        Phoenix.PubSub.local_broadcast(MyApp.PubSub, topic, msg)
      end

      # fetch existing presence information for the left users and broadcast the
      # event to all subscribers
      for {user_id, presence} <- leaves do
        IO.inspect(joins, label: "LEAVES")
        metas =
          case Map.fetch(presences, user_id) do
            {:ok, presence_metas} -> presence_metas
            :error -> []
          end

        user_data = %{user: presence.user, metas: metas}
        msg = {MyApp.PresenceClient, {:leave, user_data}}
        Phoenix.PubSub.local_broadcast(MyApp.PubSub, topic, msg)
      end

      {:ok, state}
    end
end

I’m able to join the channel but get the following error:

(KeyError) key :user not found in: %{metas: [%{user: 1, online_at: "1728611576", phx_ref: "F_1DEghkHFXOsARm"}]}

I think that the error is due to this line:

user_data = %{user: presence.user, metas: Map.fetch!(presences, user_id)}

I’d be grateful if someone could point me in the direction of resolving this error.

Many thanks and apologies if this duplicates another post - I couldn’t find anything related to this on the forum.

This is called because this line
`

`
should be

 user_data = %{user: user_id, metas: Map.fetch!(presences, user_id)}

and

  user_data = %{user: presence.user, metas: metas}

should be

user_data = %{user: user_id, metas: metas}

I wasn’t looking closely enough at the data structure for presences and presence.

Hope it helps someone.

1 Like