问题描述
我正在使用Elixir Channels编写应用程序以处理实时事件.我了解每个客户端将打开1个套接字,并且可以在其上多路复用多个通道.因此,我的应用程序是一个聊天应用程序,其中用户属于多个群组聊天的一部分.我有一个名为MessageChannel的Phoenix频道,其中的join方法将处理动态主题.
I'm writing an application using Elixir Channels to handle realtime events. I understand that there will be 1 socket open per client and can multiplex multiple channels over it. So my app is a chat application where users are part of multiple group chats. I have 1 Phoenix Channel called MessageChannel where the join method will handle dynamic topics.
def join("groups:" <> group_id, payload, socket) do
....
比方说,约翰加入了群组/主题A和B,而鲍勃只加入了群组/主题B.当约翰向群组/主题A发送消息时,broadcast!/3
也会将该消息发送给鲍勃吗?因为handle_in
没有将消息发送到哪个主题/组的上下文.
Let's say John joins groups/topics A and B while Bob only join group/topic B. When john sends a message to group/topic A, broadcast!/3
will also send that message to Bob too correct? Because handle_in
doesn't have a context of which topic/group the message was sent to.
我将如何处理,这样鲍勃(Bob)不会收到发送到A组的事件.我在设计这项权利吗?
How would I handle it so that Bob doesn't receive the events that was sent to group A. Am I designing this right?
推荐答案
调用Phoenix.Channel.broadcast/3
时,显然确实具有与消息关联的主题(从签名中不明显).您可以在此channel.ex行上看到以开始的代码:
When Phoenix.Channel.broadcast/3
is called, apparently it does have the topic associated with the message (which is not obvious from the signature). You can see the code starting on this line of 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
因此,当使用套接字调用broadcast/3
时,它会匹配当前主题,然后调用基础 Server.broadcast/4
.
So when the call to broadcast/3
is made using the socket, it pattern matches out the current topic, and then makes a call to the underlying Server.broadcast/4
.
(如果您像我一样好奇,这会反过来调用基础 PubSub.broadcast/3
可以做一些分配魔术,将呼叫路由到您配置的pubsub实现服务器,最有可能使用pg2,但我离题了...)
(If you're curious like I was, this in turn makes a call to the underlying PubSub.broadcast/3
which does some distribution magic to route the call to your configured pubsub implementation server, most likely using pg2 but I digress...)
因此,通过阅读 Phoenix.Channel
文档,但他们确实在传入事件:
因此,它仅在此套接字的主题"上广播.他们在同一页面上定义主题为:
So it's only being broadcasted "on this socket's topic". They define topic on that same page as:
因此,在您的示例中,主题"实际上是topic:subtopic对命名空间字符串:"groups:A"
和"groups:B"
. John必须在客户端上分别订阅这两个主题,因此,即使它们使用相同的套接字,您实际上也会引用两个不同的通道.因此,假设您使用的是javascript客户端,则频道创建看起来像这样:
So in your example, the "topics" are actually the topic:subtopic pair namespace strings: "groups:A"
and "groups:B"
. John would have to subscribe to both of these topics separately on the client, so you would actually have references to two different channels, even though they're using the same socket. So assuming you're using the javascript client, the channel creation looks something like this:
let channelA = this.socket.channel("groups:A", {});
let channelB = this.socket.channel("groups:B", {});
然后,当您要从客户端在通道上发送消息时,您仅使用具有主题的通道,如上所述,该主题在服务器上与模式匹配.
Then when you go to send a message on the channel from a client, you are using only the channel that has a topic that gets pattern matched out on the server as we saw above.
channelA.push(msgName, msgBody);
这篇关于凤凰频道-每个插槽多个频道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!