问题描述
我正在尝试广播到我应用中的其他频道,但无法正常工作.我也试图写一个测试,但是我不确定怎么做.
I'm trying to broadcast to a different channel in my app but I can not get it to work. Also I trying to write a test but I'm not sure how.
据我所知,我成功地广播了来自notification_channel的消息,但在chat_channel中未收到该消息.
From what I can gather I succeed in broadcasting the message from the notification_channel but it's not received in chat_channel.
通知应发送到聊天室.
notification_channel.ex
def handle_in("new:group:recommendation", msg, socket) do
payload = %{
message: msg["message"],
url: msg["url"],
title: msg["title"],
user_name: get_name_of_user(socket.assigns.user_grapqhl_id),
user_grapqhl_id: socket.assigns.user_grapqhl_id
}
IO.puts "incomming"
IO.inspect msg
Enum.map(msg["groups"], fn(x) ->
App.Endpoint.broadcast_from! self(), "chat:"<>x,
"new:recommendation", payload
end)
{:reply, :ok, socket}
end
chat_channel.ex
def handle_in("new:recommendation", msg, socket) do
IO.puts "i am a recommendation !"
IO.inspect msg
chat_msg = %{
"creator_id" => msg["user_grapqhl_id"],
"text" => msg["message"],
"creator_name" => msg["user_name"]
}
broadcast! socket, "new:msg", create_chat_msg(chat_msg,socket)
{:reply, :ok, socket}
end
测试
test "do we send a new:recommendation to chat ?", %{guardian_token: guardian_token} do
nils_base_64 = Base.encode64("user:nils")
{:ok, socket} = connect(UserSocket, %{})
{:ok, _, socket1} = subscribe_and_join(socket, "notifications:"<>nils_base_64, %{"guardian_token" => guardian_token})
{:ok, _, socket} = subscribe_and_join(socket1, "chat:Y2hhdDpjaGF0Mw==", %{"guardian_token" => guardian_token})
payload = %{
"message" => "look at this cool thing!",
"url" => "link to stuff",
"title" => "AWESOME EVENT",
"groups" => ["Y2hhdDpjaGF0Mw==", "Y2hhdDpwdWJsaWM="]
}
reply = %{message: "look at this cool thing!", title: "AWESOME EVENT", url: "link to stuff", user_grapqhl_id: nils_base_64, user_name: "Nils Eriksson"}
ref = push socket1, "new:group:recommendation", payload
assert_reply ref, :ok
assert_broadcast "new:recommendation", ^reply
end
此测试通过,我可以通过更改reply
使其失败或评论广播.通过将handle_in
更改为在chat_channel
中接收fail:please
,我无法使它失败.如果我发送更改,这是它会抱怨的事情ref = push socket1, "new:group:recommendation", payload
在这种情况下ref = push socket, "new:group:recommendation", payload
并不令人惊讶.
This test passes and i can get it to fail by changing the reply
or commenting out the broadcast. I can not get it to fail by changing the handle_in
to receive fail:please
in chat_channel
.That is something that it would complain on if i would send change thisref = push socket1, "new:group:recommendation", payload
to ref = push socket, "new:group:recommendation", payload
not supprising in that case.
这就是电线上的东西.
Process mailbox:
%Phoenix.Socket.Message{event: "init:msgs", payload: %{messages: []}, ref: nil, topic: "chat:Y2hhdDpjaGF0Mw=="}
%Phoenix.Socket.Broadcast{event: "new:recommendation", payload: %{message: "look at this cool thing!", title: "AWESOME EVENTs", url: "link to stuff", user_grapqhl_id: "dXNlcjpuaWxz", user_name: "Nils Eriksson"}, topic: "chat:Y2hhdDpjaGF0Mw=="}
%Phoenix.Socket.Message{event: "new:recommendation", payload: %{message: "look at this cool thing!", title: "AWESOME EVENTs", url: "link to stuff", user_grapqhl_id: "dXNlcjpuaWxz", user_name: "Nils Eriksson"}, ref: nil, topic: "chat:Y2hhdDpjaGF0Mw=="}
我使用通道身份验证,因为我使用的elm软件包尚不支持套接字级别的身份验证.这就是chat
I use channel authentication since the elm package i use does not support authentication on socket level yet. so this is what it looks like in chat
def join("chat:" <> chat_id, %{"guardian_token" => token}, socket) do
IO.puts chat_id
case sign_in(socket, token) do
{:ok, authed_socket, _guardian_params} ->
Process.flag(:trap_exit, true)
send(self, {:after_join})
[_type, node_chat_id] = Node.from_global_id(chat_id)
{:ok, assign(authed_socket, :chat_id, node_chat_id)}
{:error, reason} ->
IO.puts "Can't join channel cuz: " <> reason
# handle error TODO
end
结束
推荐答案
由于您在Endpoint
中使用了broadcast_from/4
.您应该在chat_channel
中使用handle_info/2
:
Since you use broadcast_from/4
from your Endpoint
.You should use handle_info/2
in your chat_channel
:
alias Phoenix.Socket.Broadcast
...
def handle_info(%Broadcast{topic: _, event: ev, payload: payload}, socket) do
IO.puts ev
IO.inspect payload
# do something with ev and payload( push or broadcast)
{:noreply, socket}
end
或者您可以从客户端收听该事件:
Or you can listen that event from your client:
chatChannel.on("new:recommendation", resp => {
// doSomething with response
}
让我们解释一下channel
和PubSub
系统如何工作.
Let's explain a bit about how the channel
and PubSub
system work.
当您要广播或推送带有有效负载的事件时,首先它将发送到PubSub
系统,然后PubSub
系统会将其发送到所有订阅者进程(channel
),主题为channel
已在PubSub
系统中注册了自己.
When you want to broadcast or push an event with payload.First it will send to the PubSub
system and then the PubSub
system will send it to all the subscriber process (channel
) with the topic that channel
registered itself with the PubSub
system.
然后,当您使用Endpoint.broadcast_from/4
广播服务器中的事件时,PubSub
系统将收到一个带有有效负载的事件,并将该事件广播到该频道注册的主题.
And when you use Endpoint.broadcast_from/4
to broadcast an event from your server.The PubSub
system will receive an event with payload and broadcast that event to the topic that channel registered.
该通道将触发handle_out
回调并将消息推送到客户端.因此,在您的chat_channel
中,您不需要handle_in
"new:recommendation"事件.您的客户只需要侦听该事件.
The channel will trigger handle_out
callback and push the message to the client.So in your chat_channel
you don't need to handle_in
"new:recommendation" event.Your client just need to listen to that event.
chatChannel.on("new:recommendation", resp => {
// do something with response
}
让我重写您的测试:
setup do
nils_base_64 = Base.encode64("user:nils")
{:ok, socket} = connect(UserSocket, %{})
{:ok, _, socket} = subscribe_and_join(socket, "notifications:"<>nils_base_64, %{"guardian_token" => guardian_token})
{:ok, socket: socket}
end
test "do we send a new:recommendation to chat ?", %{socket: socket} do
MyApp.Endpoint.subscribe("chat:Y2hhdDpjaGF0Mw==")
payload = %{
"message" => "look at this cool thing!",
"url" => "link to stuff",
"title" => "AWESOME EVENT",
"groups" => ["Y2hhdDpjaGF0Mw==", "Y2hhdDpwdWJsaWM="]
}
reply = %Phoenix.Socket.Broadcast{message: "look at this cool thing!",
title: "AWESOME EVENT",
url: "link to stuff",
user_grapqhl_id: nils_base_64,
user_name: "Nils Eriksson"}
ref = push socket, "new:group:recommendation", payload
assert_reply ref, :ok
assert_receive ^reply
end
通过subscribe
到您要收听的主题,可以确保您的频道收到了带有assert_receive
的消息.这就是将broadcast
测试到其他渠道的方法.
By subscribe
to the topic that you want to listen you can make sure that your channel is received the message with assert_receive
.That is the way to test broadcast
to a different channel.
试一试告诉我.测试将通过.
Give it a try and tell me.The test will pass.
这篇关于广播到不同的频道Phoenix 1.1.6的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!