defmodule ProcessHub.Initializer do
@moduledoc """
The main `ProcessHub` initializer supervisor module.
This module is responsible for starting all the child processes of `ProcessHub`.
"""
alias ProcessHub.Utility.Name
alias :blockade, as: Blockade
use Supervisor
@doc "Starts a `ProcessHub` instance with all its children."
@spec start_link(ProcessHub.t()) :: {:ok, pid()} | {:error, term()}
def start_link(%ProcessHub{} = hub_settings) do
Supervisor.start_link(__MODULE__, hub_settings, name: Name.initializer(hub_settings.hub_id))
end
def start_link(_), do: {:error, :expected_hub_settings}
@doc "Starts a `ProcessHub` instance with all its children."
@spec stop(atom()) :: :ok | {:error, :not_alive}
def stop(hub_id) do
if ProcessHub.is_alive?(hub_id) do
Supervisor.stop(Name.initializer(hub_id))
else
{:error, :not_alive}
end
end
@impl true
def init(%ProcessHub{hub_id: hub_id} = hub) do
managers = %{
coordinator: Name.coordinator(hub_id),
event_queue: Name.event_queue(hub_id),
distributed_supervisor: Name.distributed_supervisor(hub_id),
task_supervisor: Name.task_supervisor(hub_id)
}
children =
storage(hub_id) ++
[
{Blockade, %{name: managers.event_queue, priority_sync: false}},
dist_sup(hub_id, managers),
{Task.Supervisor, name: managers.task_supervisor},
{ProcessHub.Coordinator, {hub_id, hub, managers}},
{ProcessHub.WorkerQueue, Name.worker_queue(hub_id)}
]
opts = [strategy: :one_for_one]
case Node.alive?() do
true -> Supervisor.init(children, opts)
false -> {:error, :local_node_not_alive}
end
end
defp dist_sup(hub_id, managers) do
%{
id: :distributed_supervisor,
start: {ProcessHub.DistributedSupervisor, :start_link, [{hub_id, managers}]},
shutdown: 60_000
}
end
defp storage(hub_id) do
[
%{
id: :process_registry,
start: {Cachex, :start_link, [[name: Name.registry(hub_id), interval: nil]]}
},
%{
id: :hook_registry,
start: {Cachex, :start_link, [[name: Name.hook_registry(hub_id), interval: nil]]}
},
%{
id: :local_storage,
start: {Cachex, :start_link, [[name: Name.local_storage(hub_id), interval: 15_000]]}
}
]
end
end