defmodule Siblings do @moduledoc """ The topmost supervisor, carrying all the workers. """ use Supervisor use Boundary, exports: [Worker] alias Siblings.{InternalWorker, Worker} @doc """ Starts the supervision subtree, holding the `PartitionSupervisor`. """ def start_link(opts \\ []) do name = Keyword.get(opts, :name, __MODULE__) children = [ # {Registry, keys: :unique, name: Registry.Siblings, partitions: System.schedulers_online()}, {PartitionSupervisor, child_spec: DynamicSupervisor, name: name} ] Supervisor.start_link(children, strategy: :one_for_one) end @doc false @impl Supervisor def init(state), do: {:ok, state} @doc """ Starts the supervised child under the `PartitionSupervisor`. """ @spec start_child(module(), Worker.id(), Worker.payload(), InternalWorker.options()) :: DynamicSupervisor.on_start_child() def start_child(worker, id, payload, opts \\ []) do {name, opts} = Keyword.pop(opts, :name, __MODULE__) {shutdown, opts} = Keyword.pop(opts, :shutdown, 5_000) spec = %{ id: {worker, id}, start: {Siblings.InternalWorker, :start_link, [worker, id, payload, opts]}, restart: :transient, shutdown: shutdown } DynamicSupervisor.start_child({:via, PartitionSupervisor, {name, {worker, id}}}, spec) end end