Current section

Files

Jump to
yggdrasil lib yggdrasil subscriber distributor.ex
Raw

lib/yggdrasil/subscriber/distributor.ex

defmodule Yggdrasil.Subscriber.Distributor do
@moduledoc """
Supervisor for `Yggdrasil.Subscriber.Manager`,
`Yggdrasil.Subscriber.Adapter` and `Yggdrasil.Subscriber.Publisher`.
"""
use Supervisor
alias Yggdrasil.Channel
alias Yggdrasil.Settings
alias Yggdrasil.Subscriber.Adapter
alias Yggdrasil.Subscriber.Manager
alias Yggdrasil.Subscriber.Publisher
@registry Settings.yggdrasil_process_registry!()
#############################################################################
# Client API.
@doc """
Starts the supervisor and its children using the `channel` as part of the
identificator for the supervision tree. It also receives the `pid` of
the first subscriber. Additionally it can receive `Supervisor` `options`.
"""
@spec start_link(
Channel.t(),
pid(),
Supervisor.options()
) :: Supervisor.on_start()
def start_link(channel, pid, options \\ [])
def start_link(%Channel{} = channel, pid, options) do
Supervisor.start_link(__MODULE__, [channel, pid], options)
end
@doc """
Stops the `supervisor`.
"""
@spec stop(Supervisor.name()) :: :ok
def stop(supervisor) do
for {module, child, _, _} <- Supervisor.which_children(supervisor) do
try do
apply(module, :stop, [child])
catch
_, _ -> :ok
end
end
Supervisor.stop(supervisor)
end
#############################################################################
# Supervisor callback.
@impl true
def init([%Channel{} = channel, pid]) do
manager_name = {:via, @registry, {Manager, channel}}
publisher_name = {:via, @registry, {Publisher, channel}}
adapter_name = {:via, @registry, {Adapter, channel}}
children = [
%{
id: Manager,
start: {Manager, :start_link, [channel, [name: manager_name]]},
restart: :transient
},
%{
id: Task,
start: {Task, :start_link, [fn -> Manager.add(channel, pid) end]},
restart: :transient
},
%{
id: Publisher,
start: {Publisher, :start_link, [channel, [name: publisher_name]]},
restart: :transient
},
%{
id: Adapter,
start: {Adapter, :start_link, [channel, [name: adapter_name]]},
restart: :transient
}
]
Supervisor.init(children, strategy: :rest_for_one)
end
end