Many thanks for your response. Apologies if not clear.
Basically, my “use case” was as follows:
In a basic game scenario there are 2 players. On the server there is a Phoenix channel process that accepts join requests to a game channel for 2 players maximum. Upon join there is an “after_join” handle info call which includes the following function to start tracking each player as follows:
defp track(user_name, player_type, socket) do
push(socket, “presence_state”, Presence.list(socket))
{:ok, _} =
Presence.track(
socket,
user_name,
# metadata map
%{
player_type: player_type,
status: “offline”
}
)
end
In the metadata I’m tracking an extra field called status. Actually, this field is not very important to either player, but only to other players who are looking for counterparts to play a game with. When 2 players join up to play a game both their statuses are set to “busy” and so are unavailable to other players.
In the same channel module I run the following to check if one player
leaves, and then use this information to decide if I have to update the
status of the other player.
intercept [“presence_diff”]
def handle_out(“presence_diff”, presences, socket) do
user = socket.assigns.user
leavers = presences.leaves |> Map.keys()
if leavers != [] do
# There is a leaver, so, take the first one from the list ...
[leaver|_] = leavers
IO.puts "Player #{leaver} left the game."
if user.player_type == :player1 do
# run some code to update the other user status ...
end
end
push(socket, "presence_diff", presences)
{:noreply, socket}
end
In the browser client there is a React function that has Phoenix
Presence.onJoin and Presence.onSync listener code initialized in a
useEffect section.
All this runs fine no problem.
The interesting thing was when I decided to add a Presence.update function to the Phoenix channel in an attempt to broadcast player status to other would-be players:
defp update(status, socket) do
user = socket.assigns.user
{:ok, _} =
Presence.update(
socket,
user.user_name,
# metadata map
%{
player_type: user.player_type,
status: status # this field is updated to a new value
}
)
end
This was then causing the handle_out presence_diff calback to fire, with what I can best describe as “join-leave” pairs for the same user key in leavers and joiners. This in turn was causing the client to report a false leave/join pair on the same device.
I can now see that I was miss-using the Phoenix Presence mechanism somewhat. I’ve found another way to broadcast player status to other users and it’s all working fine now.