Broadcast to custom Phoenix.Socket.Transport implementation

I’m trying to create a custom implementation of of the Phoenix.Socket.Transport, so that I can connect to the server using standard websockets. Currently its very similar to the EchoSocket implementation in the Phoenix.Socket.Transport docs.

How do I broadcast to the connected users from outside of the Transport module? . With normal channels I have used:

MyApp.Endpoint.broadcast!("example:channel", "message", %{"message": "hello"})

But I’m not receiving the message. Thanks in advance for any help.

Hi @JorisKok, you should subscribe these processes to example:channel topic, right?

1 Like

@stefan_z If I use the example code from the Phoenix.Socket.Transport docs, that means that I should spawn a process in child_spec, and then subscribe to the example:channel via Phoenix.PubSub. Is that the correct way to go?

defmodule EchoSocket do
  @behaviour Phoenix.Socket.Transport

  def child_spec(opts) do
    # We won't spawn any process, so let's return a dummy task
    %{id: __MODULE__, start: {Task, :start_link, [fn -> :ok end]}, restart: :transient}
  end

  def connect(state) do
    # Callback to retrieve relevant data from the connection.
    # The map contains options, params, transport and endpoint keys.
    {:ok, state}
  end

  def init(state) do
    # Now we are effectively inside the process that maintains the socket.
    {:ok, state}
  end

  def handle_in({text, _opts}, state) do
    {:reply, :ok, {:text, text}, state}
  end

  def handle_info(_, state) do
    {:ok, state}
  end

  def terminate(_reason, _state) do
    :ok
  end
end

So Channels and Sockets are two different abstractions. Channels is an abstraction for message passing using pubsub. While sockets are at their core just a way for outside systems to connect to an elixir server. They only become connected through Phoenix.Socket, which implements Phoenix.Socket.Transport, but handles all the interaction between the websocket or longpolling connected client and it’s local channels implementation and the channels code on the server.

1 Like

Hi @JorisKok, it depends on your architecture and what you want to resolve.
But in this example if you want to handle broadcasted messages over specific topic and pass them towards the client, you can do subscribe in init/1 callback and handle these massages in handle_info/2 callback. After message is handled by handle_info/2 you can continue the socket with reply Phoenix.Socket.Transport — Phoenix v1.6.15 :+1: