1

I'm using websocket transport with Phoenix Channels, but I'm trying to provide a clean API for consumers without a Phoenix.Socket client to use with just websockets.

For simplicity, I'd like to auto-subscribe users to various channels when they open a session.

Currently I have something like:

defmodule MyWeb.UserSocket do
  require Logger
  use Phoenix.Socket
  alias Exchange.{Account, ApiKey}

  channel "room:time", MyWeb.TimeChannel
  channel "alpha:*", MyWeb.AlphaChannel
  channel "beta:*", MyWeb.BetaChannel

  def connect(%{"api-key" => _} = params, socket, connect_info) do
    with %{"api-key" => api_key, "api-expires" => api_expires, "api-signature" => api_signature} <-
           params,
         {:ok, %ApiKey{} = key} <- ApiKey.fetch(api_key),
         {:ok, %Account{} = account} <-ApiKey.authorize(...)) do
      Logger.info("Authorized account #{account.account_id} via API key on websocket")

      #JOIN CHANNELS HERE

      {:ok, assign(socket, :account, account)}
    else
      {:error, e} ->
        Logger.error("Websocket auth error #{inspect(e)}")
        {:ok, socket}
    end
  end

end

What do I need to put in "Join Channels Here" to get it to subscribe?

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
cjm2671
  • 18,348
  • 31
  • 102
  • 161

2 Answers2

0

this might be too simple but have you tried

Phoenix.PubSub.subscribe(MyApp.PubSub, "topic")

?

Documentation - https://hexdocs.pm/phoenix_pubsub/Phoenix.PubSub.html

Julien C
  • 220
  • 2
  • 6
  • Thanks! This appears to subscribe the current process to receive messages from a channel, but I think we're looking for something that takes and returns a socket I.e. %Socket{} = subscribe(socket, room) – cjm2671 Oct 13 '20 at 22:33
0

The answer to this question was not to use Phoenix Channels on the interface, but write a separate Transport implementation that subscribed to Phoenix.

I created a new Socket Transport by defining a new module:

@behaviour Phoenix.Socket.Transport

And provided a socked in endpoint.ex:

socket "/realtime", MyWeb.MyCustomSocket, websocket: true

This pattern follows a GenServer type layout. I subscribed to the Phoenix Channels I wanted in init and then re-emitted these events to the socket.

This created a one-way websocket that doesn't require any knowledge of Socket to connect and listen to.

cjm2671
  • 18,348
  • 31
  • 102
  • 161