Presence.get_by_key returns inconsistent type: list or map

Presence.get_by_key/2 returns a empty List for nonexistent key:

[]

but returns a Map when the key exists, for example:

%{
  metas: [
    %{online_at: 1596170493, phx_ref: "Fia8m0t_MK8qfhrB"}
  ]
}

There’s also a test case to support these two cases: presence_test.exs#L60

But on the docs page, it says to return a List as well for existing keys:

iex> MyPresence.get_by_key("room:1", "user1")
[%{name: "User 1", metas: [%{device: "Desktop"}, %{device: "Mobile"}]}]

I found it a bit confusing. Apparently either the docs needs to be fixed, or the implementation code.

From the docs, the result should even be wrapped in a map with string keys.

You’re right… docs don’t make sense. I’ve just run a test and noticed a map instead of a list.

iex(19)> APIWeb.Presence.get_by_key("device:1", "1")
%{metas: [%{online_at: "1640969072", phx_ref: "FsXkrVnrH3i7oQDF"}]}

although list/1 works as expected:

iex(26)> APIWeb.Presence.list "device:1"
%{"1" => %{metas: [%{online_at: "1640969072", phx_ref: "FsXkrVnrH3i7oQDF"}]}}

I created the condition below to solve inconsistencies:

topic
    |> Presence.get_by_key(key)
    |> case do
      %{} -> :online
      [] -> :offline
      _ -> :unknown
    end

That documentation block moved and sprouted the extra [ ] in this commit:

Both the typespec (presences is defined as %{String.t => %{metas: [map()]}} and the test for get_by_key agree with not returning a list.

1 Like