Current section

Files

Jump to
phoenix_socket_client lib phoenix socket_client supervisor.ex
Raw

lib/phoenix/socket_client/supervisor.ex

defmodule Phoenix.SocketClient.Supervisor do
@moduledoc """
The main supervisor for the Phoenix Socket Client.
"""
use Supervisor
@doc """
Starts the socket client supervisor.
## Options
* `:name` - The name to register the supervisor.
* `:url` - The WebSocket URL.
* `:params` - The parameters to send on connection.
* `:headers` - The headers to send on connection.
* `:transport` - The transport to use.
* `:heartbeat_interval` - The heartbeat interval in milliseconds.
* `:reconnect_interval` - The reconnect interval in milliseconds.
* `:reconnect?` - Whether to reconnect automatically.
* `:auto_connect` - Whether to connect automatically on startup.
* `:json_library` - The JSON encoder/decoder module to use.
* `:vsn` - The Phoenix Channels protocol version.
* `:topic_channel_map` - A map from a topic string to a channel module.
* `:default_channel_module` - The default channel module to use.
* `:default_channel_params` - The default parameters to use for channels.
"""
@spec start_link(keyword()) :: Supervisor.on_start()
def start_link(opts) do
name = Keyword.get(opts, :name, Phoenix.SocketClient)
opts = Keyword.put(opts, :name, name)
Supervisor.start_link(__MODULE__, opts, name: name)
end
@impl true
def init(opts) do
sup_pid = self()
opts = Keyword.put(opts, :sup_pid, sup_pid)
name = Keyword.get(opts, :name)
default_registry_name =
name
|> to_string()
|> String.replace_leading("Elixir.", "")
|> String.split(["_", "."])
|> Enum.map_join(&String.capitalize/1)
|> (&(&1 <> "ChannelRegistry")).()
|> String.to_atom()
registry_name = Keyword.get(opts, :registry_name, default_registry_name)
# Get serializer from opts for MessageProcessor
serializer = Phoenix.SocketClient.Message.serializer(Keyword.get(opts, :vsn, "2.0.0"))
opts =
opts |> Keyword.put(:registry_name, registry_name) |> Keyword.put(:serializer, serializer)
children = [
{Registry, keys: :unique, name: registry_name},
{Phoenix.SocketClient.Agent, opts}
|> Supervisor.child_spec(id: :socket_state),
{Phoenix.SocketClient.HibernationManager, opts}
|> Supervisor.child_spec(id: :hibernation_manager),
{Phoenix.SocketClient.RouteCache, opts}
|> Supervisor.child_spec(id: :route_cache),
{Phoenix.SocketClient.MessageProcessor, opts}
|> Supervisor.child_spec(id: :message_processor),
{Phoenix.SocketClient.Socket, opts}
|> Supervisor.child_spec(id: :socket),
{Phoenix.SocketClient.ChannelManager, opts}
|> Supervisor.child_spec(id: :channel_manager),
{Task,
fn ->
# Store registry name in agent state for fast access
case Phoenix.SocketClient.get_process_pid(sup_pid, :socket_state) do
nil -> :ok
state_pid -> Phoenix.SocketClient.Agent.put(state_pid, :registry_name, registry_name)
end
# Register socket process with hibernation manager
case {Phoenix.SocketClient.get_process_pid(sup_pid, :hibernation_manager),
Phoenix.SocketClient.get_process_pid(sup_pid, :socket)} do
{nil, _} ->
:ok
{_, nil} ->
:ok
{hm_pid, socket_pid} ->
Phoenix.SocketClient.HibernationManager.register_process(
hm_pid,
socket_pid,
{registry_name, :socket}
)
end
end}
|> Supervisor.child_spec(id: :post_start)
]
Supervisor.init(children, strategy: :rest_for_one)
end
end