Sending messages to a Phoenix.Channel process... how do I find it's PID?

I am following the docs and have built a basic channels application that works. However I want to send messages down the channel which originate from another process. Therefore I want to send messages from that other process, to the Phoenix.Channel process. I understand that Phoenix.Channel is built on top of GenServer and so handle_info will be usable, but how do I find out the Phoenix.Channel PID in the first place, since it is launched independently of my code?

Basically what is the canonical way of handling this situation, ie where outside processes want to communicate with the Phoenix.Channel so as to get it to send their messages to clients? Is the canonical way to get the PID of the Phoenix.Channel, and implement handle_info? If so how do I get the PID? I could write a function that can be called from the third party so:

defmodule HelloWeb.RoomChannel do
  use Phoenix.Channel

  def my_pid() do
    self()
  end

And then just call that. But in that case how do I know if my Phoenix.Channel process is running, when I start asking it for its PID at application launch? Can I be sure it’ll be running, and therefore respond to that my_pid() call, before my third party GenServer starts?

I think you are confused about how channels work. A “channel process” is something that is created for each and every client that subscribes to a topic. If you have the topic room:1 there is no single process that owns that topic, and if there are no clients subscribed to it, then there aren’t any processes related to it at all.

Generally speaking when interacting with channels you are best off using MyAppWeb.Endpoint.broadcast to broadcast messages to a topic instead of trying to sort out which channels are subscribed to it.

Finally

This returns the PID of the caller not of the channel. Elixir modules are not classes or objects, calling self() doesn’t change just because it’s inside the channel module, it always returns the pid of the caller.

5 Likes