Programming Phoenix LiveView B4.0: incorrect Presence tracking code (pages 247-250)

The code provided for tracking user’s presence on the product detail page seems more complicated than it needs to be, and for me at least, it doesn’t actually work as provided – it only tracks the first user that visits the product, but ignores any user after that – it seems that the call to Presence.update doesn’t properly update the list of e-mail addresses.

I first tried to re-trace my steps and see if I missed something important, but then I just decided to re-write the code using a simplified logic for presence tracking, and a bit more convoluted logic for formatting the list of users. Here’s my suggested fix, if interested:

# lib/pento_web/presence.ex
def track_user(pid, product, token) do
  user = Accounts.get_user_by_session_token(token)

  Presence.track(pid, @user_activity_topic, product.name, %{email: user.email})
end
# lib/pento_web/live/user_activity_live.ex
defp assign_user_activity(socket) do
  presence_map = Presence.list(@user_activity_topic)

  user_activity =
    presence_map
    |> Enum.map(fn {product_name, _data} ->
      emails =
        get_in(presence_map, [product_name, :metas])
        |> Enum.map(& &1.email)
        |> Enum.uniq()
        |> Enum.sort()

      {product_name, emails}
    end)

  assign(socket, :user_activity, user_activity)
end
<!-- user_activity_live.html.leex -->
<div class="user-activity-component">
  <h2>User Activity</h2>
  <p>Active users currently viewing games</p>
  <div>
    <%= for {product_name, emails} <- @user_activity do %>
      <h3><%= product_name %></h3>
      <ul>
        <%= for email <- emails do %>
          <li><%= email %></li>
        <% end %>
      </ul>
    <% end %>
  </div>
</div>

Hi @Cellane! Thanks so much for sharing this approach. You are absolutely right that there is a bug in the Presence code in the chapter, as it’s written. The current call to Presence.update actually returns {:error, :nopresence} since we are trying to update data for a pid that is not yet being tracked. You change to only call Presence.track in the track_user/3 function is the way to go. Then, the code to list user presences can be updated accordingly.

You’ll find these changes, and some updated explanations, in either the next Beta release or the one following that.

Thanks again!

1 Like