ed1*_*d1t 3 sockets elixir elixir-framework phoenix-framework phoenix-channels
我正在使用Elixir Channels编写一个应用程序来处理实时事件.我知道每个客户端将打开1个套接字,并且可以在其上复用多个通道.所以我的应用程序是一个聊天应用程序,用户是多个群聊的一部分.我有一个名为MessageChannel的Phoenix Channel,其中join方法将处理动态主题.
def join("groups:" <> group_id, payload, socket) do
....
Run Code Online (Sandbox Code Playgroud)
假设John加入群组/主题A和B而Bob只加入群组/主题B.当john向群组/主题A发送消息时,广播!/ 3也会将该消息发送给Bob太正确了吗?因为handle_in没有发送消息的主题/组的上下文.
如何处理它以便Bob不会收到发送给A组的事件.我设计得对吗?
小智 5
因为
handle_in没有发送消息的主题/组的上下文.
当Phoenix.Channel.broadcast/3被调用时,显然它确实具有与消息相关联的主题(签名中不明显).你可以看到从这行channel.ex开始的代码:
def broadcast(socket, event, message) do
%{pubsub_server: pubsub_server, topic: topic} = assert_joined!(socket)
Server.broadcast pubsub_server, topic, event, message
end
Run Code Online (Sandbox Code Playgroud)
因此,当broadcast/3使用套接字进行调用时,它模式匹配当前主题,然后调用底层Server.broadcast/4.
(如果你像我一样好奇,这反过来调用底层PubSub.broadcast/3,它会做一些分配魔术来将调用路由到你配置的pubsub实现服务器,很可能使用pg2,但我离题...)
因此,我发现这种行为在阅读Phoenix.Channel文档时并不明显,但是他们在传入事件的phoenixframework频道页面中明确说明了这一点:
broadcast!/3将通知此套接字主题的所有已加入的客户端并调用其handle_out/3回调.
所以它只是在"这个插座的主题"上播出.他们在同一页面上定义主题:
topic - 字符串主题或主题:子主题对命名空间,例如"messages","messages:123"
所以在你的例子中,"主题"实际上是主题:子主题对命名空间字符串:"groups:A"和"groups:B".John必须在客户端上单独订阅这两个主题,因此您实际上会引用两个不同的通道,即使它们使用相同的套接字.因此,假设您使用的是javascript客户端,则通道创建看起来像这样:
let channelA = this.socket.channel("groups:A", {});
let channelB = this.socket.channel("groups:B", {});
Run Code Online (Sandbox Code Playgroud)
然后,当您从客户端在通道上发送消息时,您只使用具有在服务器上匹配模式的主题的通道,如上所述.
channelA.push(msgName, msgBody);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2840 次 |
| 最近记录: |