From 2d30e376224b3ac268377acaa0cc54ef65c52575 Mon Sep 17 00:00:00 2001 From: Jasper Martin Date: Wed, 8 Jan 2025 22:43:03 +1100 Subject: [PATCH] Improve Phoenix.Presence.get_by_key/2 - Change presence typespec, and use presence type for presences typespec. - Return `nil` for empty presence on `Presence.get_by_key/2`. - Assert is_nil instead of empty array on `Presence.get_by_key/2` test. - Improve documentation of `Presence.get_by_key/2` callback. --- lib/phoenix/presence.ex | 18 ++++++++++++------ test/phoenix/presence_test.exs | 6 +++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/phoenix/presence.ex b/lib/phoenix/presence.ex index ad81c106a8..bff26caff2 100644 --- a/lib/phoenix/presence.ex +++ b/lib/phoenix/presence.ex @@ -189,8 +189,8 @@ defmodule Phoenix.Presence do """ - @type presences :: %{String.t() => %{metas: [map()]}} - @type presence :: %{key: String.t(), meta: map()} + @type presence :: %{metas: [map()]} + @type presences :: %{String.t() => presence} @type topic :: String.t() @doc """ @@ -297,12 +297,19 @@ defmodule Phoenix.Presence do devices, could return: iex> MyPresence.get_by_key("room:1", "user1") - [%{name: "User 1", metas: [%{device: "Desktop"}, %{device: "Mobile"}]}] + %{ + name: "User 1", + additional_info: %{}, + metas: [%{device: "Desktop"}, %{device: "Mobile"}] + } + + iex> MyPresence.get_by_key("room:1", "untracked_user") + nil Like `c:list/1`, the presence metadata is passed to the `fetch` callback of your presence module to fetch any additional information. """ - @callback get_by_key(Phoenix.Socket.t() | topic, key :: String.t()) :: [presence] + @callback get_by_key(socket_or_topic :: Phoenix.Socket.t() | topic, key :: String.t()) :: presence | nil @doc """ Extend presence information with additional data. @@ -540,8 +547,7 @@ defmodule Phoenix.Presence do string_key = to_string(key) case Phoenix.Tracker.get_by_key(module, topic, key) do - [] -> - [] + [] -> nil [_ | _] = pid_metas -> metas = Enum.map(pid_metas, fn {_pid, meta} -> meta end) diff --git a/test/phoenix/presence_test.exs b/test/phoenix/presence_test.exs index 8b24f09c27..fce932aadf 100644 --- a/test/phoenix/presence_test.exs +++ b/test/phoenix/presence_test.exs @@ -98,7 +98,7 @@ defmodule Phoenix.PresenceTest do test "get_by_key/2 returns metadata for key", config do pid2 = spawn(fn -> :timer.sleep(:infinity) end) pid3 = spawn(fn -> :timer.sleep(:infinity) end) - assert MyPresence.get_by_key(config.topic, 1) == [] + assert is_nil(MyPresence.get_by_key(config.topic, 1)) assert {:ok, _} = MyPresence.track(self(), config.topic, 1, %{name: "u1"}) assert {:ok, _} = MyPresence.track(pid2, config.topic, 1, %{name: "u1.2"}) assert {:ok, _} = MyPresence.track(pid3, config.topic, 2, %{name: "u1.2"}) @@ -106,8 +106,8 @@ defmodule Phoenix.PresenceTest do assert %{extra: "extra", metas: [%{name: "u1", phx_ref: _}, %{name: "u1.2", phx_ref: _}]} = MyPresence.get_by_key(config.topic, 1) - assert MyPresence.get_by_key(config.topic, "another_key") == [] - assert MyPresence.get_by_key("another_topic", 2) == [] + assert is_nil(MyPresence.get_by_key(config.topic, "another_key")) + assert is_nil(MyPresence.get_by_key("another_topic", 2)) end test "handle_diff broadcasts events with default fetched data",