2016-07-24 5 views
3

Ich versuche, auf einen anderen Kanal in meiner App zu übertragen, aber ich kann es nicht funktionieren. Ich versuche auch einen Test zu schreiben, aber ich weiß nicht wie.Broadcast zu verschiedenen Kanal Phoenix 1.1.6

Von dem, was ich sammeln kann, gelingt es mir, die Nachricht aus dem notification_channel zu senden, aber es wird nicht in chat_channel empfangen.

Benachrichtigung sollte an Chat senden.

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

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 

Dieser Test p asses und ich kann es zum Scheitern bringen, indem Sie die reply ändern oder die Sendung auskommentieren. Ich kann es nicht zum Scheitern bringen, indem ich die handle_in ändere, um fail:please in chat_channel zu erhalten. Das ist etwas, über das es sich beschweren würde, wenn ich diese Änderung ref = push socket1, "new:group:recommendation", payload zu ref = push socket, "new:group:recommendation", payload nicht in diesem Fall unterstützen würde.

Dies ist, was auf dem Draht ist.

Ich benutze die Kanalauthentifizierung, da das von mir verwendete elm-Paket die Authentifizierung auf Socket-Ebene noch nicht unterstützt. so ist es das, was es sieht aus wie 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 

Ende

Antwort

4

Da Sie broadcast_from/4 von Ihrem Endpoint verwenden .Sie handle_info/2 in Ihrem chat_channel verwenden sollten:

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 

Oder können Sie dieses Ereignis hören von Ihrem Kunden:

chatChannel.on("new:recommendation", resp => { 
    // doSomething with response 
} 

Edit:

Lasst uns ein wenig darüber, wie die channel und PubSub System Arbeit erklären.

Wenn Sie eine Veranstaltung mit payload.First auszustrahlen oder schieben Sie es an das PubSub System senden und dann dem PubSub System wird es für alle Teilnehmerprozesse (channel) mit dem Thema senden, dass channel selbst registriert mit den PubSub System.

Und wenn Sie Endpoint.broadcast_from/4 verwenden, um ein Ereignis von Ihrem Server zu senden. Das PubSub System wird ein Ereignis mit Payload empfangen und dieses Ereignis an das Thema senden, das registriert wurde.

Der Kanal wird handle_out Rückruf auslösen und die Nachricht an den Client senden. Also in Ihrem chat_channel müssen Sie nicht handle_in "new: Empfehlung" -Ereignis.Ihr Client muss nur auf dieses Ereignis zu hören.

chatChannel.on("new:recommendation", resp => { 
    // do something with response 
} 

Und lassen Sie mich Ihren Test umschreiben:

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 

von subscribe zum Thema, das Sie Sie sicherstellen können, hören möchten, dass Ihr Kanal die Nachricht mit assert_receive empfangen wird. So testen Sie broadcast auf einen anderen Kanal.

Probieren Sie es aus und sagen Sie mir. Der Test wird bestanden.

+0

Ist es wichtig, dass ich Channel Auth habe? Nichts hat sich geändert, als ich das versuchte. Ich habe es geschafft, externe Kanäle zu abonnieren, für was auch immer es sich lohnt. – Note89

+0

oh dein Test ist bereits bestanden. So, was ist das Problem? Ich dachte, du kannst nicht auf einen anderen Kanal übertragen? – TheAnh

+0

Ja, sie bestehen, aber sie testen nicht, ob sie im Chat-Kanal empfangen werden. Die Nachricht wird gesendet, aber nicht abgeholt. – Note89

0

Verwenden Sie App.Endpoint.broadcast topic, event, payload mit dem Thema Ihres Chat-Kanals. Es sollte funktionieren.

Verwandte Themen