Connecting to Channel from within application

Hey everyone, here’s my use case: I have a channel that sends events to a GenServer running a simulation and that GenServer responds, as well as sends broadcast back to the channel. Now I want to create another GenServer that can connect to that same channel and send and receive messages like any other client.

I’ve done some searching and noticed there are libraries that implement a full client, as in use websockets to connect to the channel, but that seems overkill since my new GenServers are running within the same application. Is there anyway to achieve this without running a full client?

Failing this I think I could just have the two GenServers communicate directly with each other but I would like to avoid creating a different communication channel within my simulation.

You can simply use PubSub. Subscribe to the channel topic to “listen in” on the channel messages. Broadcast on the channel topic to send messages to channel processes.

def init(...) do
  MyApp.Endpoint.subscribe("room:123")
  ...
end

alias Phoenix.Socket.Broadcast
def handle_info(%Broadcast{topic: "new_msg"} = msg, state) do
  # do something on new chat message broadcasted by channel process
end

def broadcast_new_msg(body) do
  MyApp.Endpoint.broadcast_from(self(), "room:123", "new_msg", %{body: body})
end

Thanks for the quick reply, Chris! This looks like it will work for my needs. A couple more questions if you don’t mind. Does subscribing to the topic trigger the topics join callback? I’m presuming it does not as the join callback takes a socket (that’s easy enough to get around in my case). From looking at the docs for PubSub, it looks like after I subscribe I need to call Process.info at some interval to get notified of incoming messages, is this correct?

No. See Chris’s usage of handle_info/2

Ah! Thanks for pointing that out. I understand now.