Трансляция на другой канал Феникс 1.1.6

Я пытаюсь транслировать на другой канал в моем приложении, но не могу заставить его работать. Также я пытаюсь написать тест, но я не уверен, как.

Из того, что я могу собрать, я преуспел в трансляции сообщения от messages_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_channel, Это то, на что он будет жаловаться, если я отправлю изменить это ref = 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

конец

2 ответа

Так как вы используете 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
}

Редактировать:

Давайте объясним немного о том, как channel а также PubSub системная работа.

Если вы хотите транслировать или отправить событие с полезной нагрузкой. Сначала оно отправит PubSub система, а затем PubSub система отправит его всем подписчикам процесса (channel) с темой channel зарегистрировался в PubSub система.

И когда вы используете Endpoint.broadcast_from/4 транслировать событие с вашего сервера. PubSub Система получит событие с полезной нагрузкой и передаст его в тему, зарегистрированную на канале.

Канал сработает handle_out перезвонить и отправить сообщение клиенту. Так в вашем chat_channel тебе не нужно handle_in Событие "new: рекомендации". Вашему клиенту просто нужно прослушать это событие.

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 на другой канал.

Попробуйте и скажите мне. Тест пройдет.

Использование App.Endpoint.broadcast topic, event, payload с темой вашего канала чата. Он должен работать.

Другие вопросы по тегам