4

アプリで別のチャンネルにブロードキャストしようとしていますが、うまくいきません。また、テストを作成しようとしていますが、方法がわかりません。

収集できることから、notification_channel からのメッセージのブロードキャストに成功しましたが、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をで受信するようfail:pleaseに変更して失敗させることはできませんchat_channelref = push socket1, "new:group:recommendation", payload その場合、これを驚かせないように変更する場合、それは文句を言うでしょう ref = push socket, "new:group:recommendation", payload

これは、ワイヤ上にあるものです。

     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

  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

終わり

4

2 に答える 2

6

broadcast_from/4あなたはあなたから使用するので、あなたの中Endpointで使用する必要handle_info/2があります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

または、クライアントからそのイベントをリッスンできます。

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

編集:

channelPubSubシステムがどのように機能するかについて少し説明しましょう。

ペイロードを使用してイベントをブロードキャストまたはプッシュする場合。最初にPubSubシステムに送信され、次にシステムはシステムに登録されたトピックとともにPubSubすべてのサブスクライバー プロセス ( ) に送信します。channelchannelPubSub

Endpoint.broadcast_from/4また、サーバーからイベントをブロードキャストするために使用するとPubSub、システムはペイロードを含むイベントを受信し、そのイベントをチャネルが登録したトピックにブロードキャストします。

チャネルはhandle_outコールバックをトリガーし、メッセージをクライアントにプッシュします。したがって、「new:recommendation」イベントchat_channelは必要ありません。クライアントはそのイベントをリッスンするだけです。handle_in

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_receivebroadcastこれは、別のチャネルをテストする方法です。

試してみて教えてください。テストはパスします。

于 2016-07-24T13:29:14.087 に答える