Current section

Files

Jump to
dynamic_supervisor_proxy lib dynamic_supervisor proxy.ex
Raw

lib/dynamic_supervisor/proxy.ex

defmodule DynamicSupervisor.Proxy do
@supervisor_restart_backoff "https://github.com/erlang/otp/pull/1287"
@moduledoc """
Starts a module-based dynamic supervisor process with a registered name.
Will wait a bit if the supervisor name is still registered on restarts.
See [Supervisor restart backoff](#{@supervisor_restart_backoff}).
"""
@doc """
Uses `DynamicSupervisor`. Also either aliases `DynamicSupervisor.Proxy` (this
module) and requires the alias or imports `DynamicSupervisor.Proxy`. Finally,
it will inject the default implementation of the `c:DynamicSupervisor.init/1`
callback.
## Examples
use DynamicSupervisor.Proxy, alias: Proxy
use DynamicSupervisor.Proxy
"""
defmacro __using__(options) do
alias = options[:alias]
if alias do
quote do
use DynamicSupervisor
alias unquote(__MODULE__), as: unquote(alias)
require unquote(alias)
@impl DynamicSupervisor
@spec init(term) :: {:ok, DynamicSupervisor.sup_flags()} | :ignore
def init(_arg), do: DynamicSupervisor.init(strategy: :one_for_one)
defoverridable init: 1
end
else
quote do
use DynamicSupervisor
import unquote(__MODULE__)
@impl DynamicSupervisor
@spec init(term) :: {:ok, DynamicSupervisor.sup_flags()} | :ignore
def init(_arg), do: DynamicSupervisor.init(strategy: :one_for_one)
defoverridable init: 1
end
end
end
@doc """
Starts a module-based dynamic supervisor process with the given `module` and
`init_arg`. The `:name` option _must_ be specified in order to register a
supervisor name. Will wait a bit if the supervisor name is still registered
on restarts. See [Supervisor restart backoff](#{@supervisor_restart_backoff}).
To start the supervisor, the `c:DynamicSupervisor.init/1` callback will be
invoked in the given `module`, with `init_arg` as its argument. The
`c:DynamicSupervisor.init/1` callback must return a supervisor specification
which can be created with the help of the `DynamicSupervisor.init/1` function.
## Examples
iex> defmodule DynSupOne do
iex> use DynamicSupervisor.Proxy
iex>
iex> def start_link(:ok), do: start_link(DynSupOne, name: DynSupOne)
iex> end
iex>
iex> children = [{DynSupOne, :ok}]
iex> options = [name: Sup, strategy: :one_for_one]
iex> {:ok, _pid} = Supervisor.start_link(children, options)
iex>
iex> %{active: 1, supervisors: 1} = Supervisor.count_children(Sup)
iex> [{name, pid, :supervisor, [name]}] = Supervisor.which_children(Sup)
iex>
iex> name == DynSupOne and pid == Process.whereis(DynSupOne)
true
iex> defmodule DynSupTwo do
iex> use DynamicSupervisor.Proxy
iex>
iex> def start_link(_), do: start_link(DynSupTwo, ??, name: DynSupTwo)
iex> end
iex>
iex> defmodule DynSupThree do
iex> use DynamicSupervisor.Proxy, alias: Proxy
iex>
iex> def start_link(OK) do
iex> Proxy.start_link(__MODULE__, name: :three)
iex> end
iex> end
iex>
iex> children = [DynSupTwo, {DynSupThree, OK}]
iex> options = [name: Sup, strategy: :one_for_one]
iex> {:ok, _pid} = Supervisor.start_link(children, options)
iex>
iex> %{active: 2, supervisors: 2} = Supervisor.count_children(Sup)
iex> children = Supervisor.which_children(Sup)
iex> pid_two = Process.whereis(DynSupTwo)
iex> pid_three = Process.whereis(:three)
iex>
iex> {DynSupTwo, pid_two, :supervisor, [DynSupTwo]} in children and
...> {DynSupThree, pid_three, :supervisor, [DynSupThree]} in children
true
"""
defmacro start_link(module, init_arg \\ nil, opts) do
quote bind_quoted: [mod: module, arg: init_arg, opts: opts] do
DynamicSupervisor.Proxy.Starter.start_link(mod, arg, opts)
end
end
end