首页 > 解决方案 > 我可以选择通过 Phoenix Presence 跟踪的特定进程/套接字吗?

问题描述

我的用例是让多个用户连接到大厅/等候室,但只有两个用户会从大厅中被选中来开始对话,之后他们应该从大厅中移除。我该如何实施?请注意,在此系统中,用户没有注册,也没有用户名。他们应该直接从网页进来。

显然trackanduntrack函数也有接受pid作为参数的变体。但是,当需要开始对话时,我不确定如何首先检索进程的 pid。

在这种情况下,该功能self()是否正确?即也许我可以写

def handle_info(:after_lobby_join, socket) do
  Presence.track(socket, "lobby", %{
    pid: self()
  })

  {:noreply, socket}
end

def handle_info(:start, socket) do
  pid1 = hd(Presence.list(socket)["lobby"][:metas])[:pid]
  # Start the conversation by sending messages individually to pid1 and pid2
  ...
  untrack(pid1, "my_app:lobby", "lobby")
  {:ok, socket}
end

或者我是否使问题过于复杂/没有正确理解存在?

还有一个phx_ref字段,但我似乎无法将其用于此目的。

此外,显然我只想向"start_conversation"被选中的两个用户发送消息,而不是大厅中的其他用户。我看到该函数push将消息发送到指定的套接字。但是,如果我在跟踪 pid,是否可以从 pid 中识别出相应的套接字?

标签: websocketelixirphoenix-frameworkuser-presence

解决方案


我最终使用个人用户渠道解决了我最初的问题。我只是让前端生成随机用户 ID。

Elixir 论坛提出了一个不使用用户频道的解决方案。它虽然不使用存在。

def handle_info({:new_user, socket}, [{us1, ref1}, {us2, ref2}]) do
  # we had 2 users, a new one joined, so that's 3
  user_sockets = [socket, us1, us2]
  # we can create a room for them now
  create_new_room(user_sockets)
  # and clean the state
  Enum.each([ref1, ref2], fn ref ->
    Process.demonitor(ref)
  end)
  {:noreply, []}
end

def handle_info({:new_user, socket}, waiting_user_sockets) do
  # otherwise just add the new users to the waiting users list
  ref = Process.monitor(socket)
  {:noreply, [{socket, ref} | waiting_user_sockets]}
end

def handle_info({:DOWN, ref, :process, _object, _reason}, waiting_user_sockets) do
  # remove the disconnected socket
end

推荐阅读