Presence not picking up user leave events?

匆匆过客 提交于 2019-12-24 18:50:30

问题


I need to perform some actions when the user leaves a channel (in most cases where they close the tab voluntarily, but there may also be a connection loss/timeout etc.)

According to posts like https://elixirforum.com/t/phoenix-presence-run-some-code-when-user-leaves-the-channel/17739 and How to detect if a user left a Phoenix channel due to a network disconnect?, intercepting the "presence_diff" event from Presence seems to be a foolproof way to go, as it should also covers the cases where the connection terminates abnormally.

Strangely, the presence_diff event seems to only be triggered when I track the user via Presence.track, but not when the user leaves.

Meanwhile, adding a terminate(reason, socket) callback in my channel correctly catches the leave event.

I wonder what could be wrong in my configuration. Or did I not understand the use of Presence correctly?

Example code:

def join("participant:" <> participant_id, _payload, socket) do
  if socket.assigns.participant_id == participant_id do
    send(self(), :after_participant_join)
    {:ok, socket}
  else
    {:error, %{reason: "unauthorized"}}
  end
end

def handle_info(:after_participant_join, socket) do
  experiment_id = socket.assigns.experiment_id

  Presence.track(socket, experiment_id, %{
    # keys to track
  })

  # Broadcast something
  # broadcast(socket, ...)

  {:noreply, socket}
end

intercept(["presence_diff"])

def handle_out("presence_diff", payload, socket) do
  # Only gets triggered at Presence.track, but not when the connection is closed.
  IO.puts("presence_diff triggered, payload is #{inspect(payload)}")

  leaves = payload.leaves

  for {experiment_id, meta} <- leaves do
    IO.puts("Leave information: #{meta}")

    # Do stuffs
    end
end

# This works, however.
def terminate(reason, socket) do
  IO.puts("terminated. #{inspect(reason)}")

  # Do stuffs.
end

回答1:


OK I think I know what happened: Each "participant:" <> participant_id topic is, as its name suggests, only subscribed to by one participant. Therefore, when that participant quits, the process also dies and nobody is able to act on the presence_diff message.

A separate process is still needed. One can call MyApp.Endpoint.subscribe from that process to subscribe to the "participant:" <> participant_id topic and act on the presence_diff messages.

Or one can set up an external monitor. See How to detect if a user left a Phoenix channel due to a network disconnect?



来源:https://stackoverflow.com/questions/53986369/presence-not-picking-up-user-leave-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!