Broadcasting to external topics

Hi, friends,

In my application, I have a channel that is responsible on sending and receiving messages from external topics (the client doesn’t need to “join” them explicitly).

I could achieve channel communication through broadcast_from and MyApp.Endpoint.broadcast_from, but… only when I join both topics (let’s say… my “core” channel and the secondary - external - topic).

My question is: is it possible to achieve channel communication (send and receive messages) with external topics without the client have to joining on them?

P.S. I’d already used MyApp.Endpoint.subscribe, without success. Here is what I’ve done 'til now:

defmodule MyApp.CommunicationChannel do
  use MyAppWeb, :channel

  def join("communication", _payload, socket) do
    {:ok, socket}
  end

  def handle_in("join_external", %{"topic" => topic}, socket) do
    MyApp.Endpoint.subscribe(topic)
    {:noreply, socket}
  end

  def handle_in("send_to_external", %{"topic" => topic} = payload, socket) do
    MyApp.Endpoint.broadcast_from! self(), topic, "receive_payload", payload
    {:noreply, socket}
  end

  def handle_in("send_to_client", payload, socket) do
    broadcast! socket, "send_to_client", payload  
  end

  def handle_info(%Phoenix.Socket.Broadcast{topic: _, event: event, payload: payload}, socket) do
    push socket, event, payload
    {:noreply, topic}
  end
end

defmodule MyApp.ReceiverChannel do
  use MyAppWeb, :channel
  
  def join("receive", _payload, socket) do
    MyApp.Endpoint.subscribe("communication")
    {:ok, socket}
  end

  def handle_in("receive_payload", payload, socket) do
    MyApp.Endpoint.broadcast_from! self(), "communication", "send_to_client", payload
    {:noreply, socket}
  end

  def handle_info(%Phoenix.Socket.Broadcast{topic: _, event: event, payload: payload}, socket) do
    push socket, event, payload
    {:noreply, topic}
  end
end

What am I doing wrong? The communication between them only works when the client subscribe to both channels.

Thanks in advance!

I’m not entirely sure but I believe you want MyApp.Endpoint.broadcast!/3 instead of MyApp.Endpoint.broadcast_from!/3. Also you shouldn’t need the MyApp.Endpoint.subscribe(topic).

Actually broadcast_from should works as well. The difference between these two functions are that sender doesn’t receive the message, because broadcast_from means send the message to everyone else.

You send to external topic twice and maybe that’s why it doesn’t work. It comes from Communication and it return there, which doesn’t make sense to me. Consider using sending regular process message and use handle_info to process it.