是否可以跟踪来自不同主题的用户存在?

时间:2016-08-05 22:29:40

标签: elixir phoenix-framework

我使用Phoenix框架为我的Elixir应用程序与WebSocket连接。我有两个不同的主题,一个用于用户,另一个用于管理员。管理员应该看到哪些用户在场。我决定使用凤凰城的Presence模块。不幸的是,您只能将当前Presence状态发送到开始跟踪的套接字。

示例代码:

def join("users", params, socket) do
  socket |> assign(:user_id, params[:user_id])

  send(self, :after_join)
  {:ok, socket}
end

def join("admins", _params, socket) do
  {:ok, socket}
end

def handle_info(:after_join, socket) do
  push(socket, "presence_state", Presence.list(socket))

  {:ok, _} = Presence.track(socket, socket.assigns[:user_id], %{
    online_at: inspect(System.system_time(:seconds))
  })

  {:noreply, socket}
end

我想在管理员的前端应用程序中监听状态更改中的事件。可以使用Phoenix.Presence吗?

2 个答案:

答案 0 :(得分:3)

您可以使用YourApp.Endpoint.broadcast/3

def handle_info(:after_join, socket) do

  {:ok, _} = Presence.track(socket, socket.assigns[:user_id], %{
    online_at: inspect(System.system_time(:seconds))
  })
  YourApp.Endpoint.broadcast "admins", "presence_state", Presence.list(socket)

  {:noreply, socket}
end

并从您的adminChannel听取presence_state

adminChannel.on("presence_state", state => {
  presences = Presence.syncState(state)
  // doSomethingWithPresences
}

您应该将YourApp.AdminChannelYourApp.UserChannel

分开

当您的客户收到presence_diff个活动时。您可以将其推送到用户频道并再次使用Endpoint.broadcast/3

userChannel.on("presence_diff", diff => {
  userChannel.push("presence_diff", diff)
}
YourApp.UserChannel中的

def handle_in("presence_diff", diff, socket) do
  YourApp.Endpoint.broadcast "admins", "presence_diff", diff
  {:noreply, socket}
end

现在你可以听你的presence_diff事件了:

adminChannel.on("presence_diff", diff => {
  presences = Presence.syncDiff(diff)
  render(presences)
}

答案 1 :(得分:1)

如果您要在其中一个频道的回调处理程序(例如handle_info/2)中设置状态跟踪,则可以对以下任意主题添加跟踪:

Presence.track(self(), "admins", socket.assigns[:user_id], %{some_metadata: "whatever"})

然后,在另一个进程的其他位置,您可以订阅admins主题,如:

YourApp.Endpoint.subscribe("admins"),此时该流程将开始接收presence_diff条消息。