Behaviours: gen_server
.
A supervisor optimized to only start children dynamically.
The standard supervisor module was designed to handle mostly static children that are started in the given order when the supervisor starts. A dynamic_supervisor starts with no children. Instead, children are started on demand via start_child/2 and there is no ordering between children. This allows the dynamic_supervisor to hold millions of children by using efficient data structures and to execute certain operations, such as shutting down, concurrently.
A dynamic supervisor is started with no children and often a name:
{ok, Pid} = dynamic_supervisor:start_link([ {name, {local, my_dynamic_supervisor}}, {strategy, one_for_one} ]).
Once the dynamic supervisor is running, we can use it to start children on demand. Given this sample gen_server:
-module(counter). -behaviour(gen_server). -export([start_link/1, inc/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). start_link(Initial) -> gen_server:start_link(?MODULE, Initial, []). inc(Pid) -> gen_server:call(Pid, inc). init(Initial) -> {ok, Initial}. handle_call(inc, _From, Count) -> {reply, Count, Count + 1}.
We can use start_child/2 with a child specification to start a counter server:
{ok, Counter1} = dynamic_supervisor:start_child(my_dynamic_supervisor, #{id => counter1, start => {counter, start_link, [0]}, restart => permanent, shutdown => 5000, type => worker, modules => [counter]}). counter:inc(Counter1). %% 0 {ok, Counter2} = dynamic_supervisor:start_child(my_dynamic_supervisor, #{id => counter2, start => {counter, start_link, [10]}, restart => permanent, shutdown => 5000, type => worker, modules => [counter]}). counter:inc(Counter2). %% 10 dynamic_supervisor:count_children(my_dynamic_supervisor). %% #{active => 2, specs => 2, supervisors => 0, workers => 2}
child_spec() = #{id := term(), start := {module(), atom(), [term()]}, restart => restart(), shutdown => shutdown(), type => child_type(), modules => modules(), significant => boolean()}
child_type() = worker | supervisor
init_option() = {strategy, strategy()} | {max_restarts, non_neg_integer()} | {max_seconds, pos_integer()} | {max_children, non_neg_integer() | infinity} | {extra_arguments, [term()]}
modules() = [module()] | dynamic
restart() = permanent | transient | temporary
shutdown() = brutal_kill | infinity | non_neg_integer()
start_option() = {name, atom() | {local, atom()} | {global, atom()} | {via, module(), term()}} | {timeout, timeout()} | {debug, [sys:debug_option()]} | {spawn_opt, [term()]}
strategy() = one_for_one
sup_flags() = #{strategy := strategy(), intensity => non_neg_integer(), period => pos_integer(), max_children => non_neg_integer() | infinity, extra_arguments => [term()], auto_shutdown => never}
count_children/1 | Returns a map containing count values for the supervisor. |
init_supervisor/1 | Receives a set of Options that initializes a dynamic supervisor. |
start_child/2 | Dynamically adds a child specification to Supervisor and starts that child. |
start_link/1 | Starts a supervisor with the given options. |
start_link/3 | Starts a module-based supervisor process with the given Module and InitArg . |
stop/1 | Synchronously stops the given supervisor with the given Reason . |
stop/2 | |
stop/3 | |
terminate_child/2 | Terminates the given child identified by Pid . |
which_children/1 | Returns a list with information about all children. |
count_children(Supervisor::pid() | atom() | {atom(), node()} | {global, atom()} | {via, module(), term()}) -> #{specs := non_neg_integer(), active := non_neg_integer(), supervisors := non_neg_integer(), workers := non_neg_integer()}
Returns a map containing count values for the supervisor.
The map contains the following keys:specs
- the number of children processesactive
- the count of all actively running child processes managed by
this supervisorsupervisors
- the count of all supervisors whether or not the child
process is still aliveworkers
- the count of all workers, whether or not the child process
is still aliveinit_supervisor(Options::[init_option()]) -> {ok, sup_flags()}
Receives a set of Options
that initializes a dynamic supervisor.
This is typically invoked at the end of the init/1
callback of
module-based supervisors.
It accepts the same Options
as start_link/1
(except for name
)
and it returns a tuple containing the supervisor options.
init(_Arg) -> dynamic_supervisor:init_supervisor([{max_children, 1000}]).
start_child(Supervisor::pid() | atom() | {atom(), node()} | {global, atom()} | {via, module(), term()}, ChildSpec::child_spec() | {module(), term()} | module()) -> {ok, pid()} | {ok, pid(), term()} | ignore | {error, term()}
Dynamically adds a child specification to Supervisor
and starts that child.
ChildSpec
should be a valid child specification.
The child process will be started as defined in the child specification.
If the child process start function returns {ok, Child}
or {ok, Child, Info}
,
then child specification and PID are added to the supervisor and
this function returns the same value.
If the child process start function returns ignore
, then no child is added
to the supervision tree and this function returns ignore
too.
If the child process start function returns an error tuple or an erroneous
value, or if it fails, the child specification is discarded and this function
returns {error, Error}
where Error
is the error or erroneous value
returned from child process start function, or failure reason if it fails.
max_children
set on the supervisor initialization, then
this function returns {error, max_children}
.
start_link(Options::[init_option() | start_option()]) -> {ok, pid()} | ignore | {error, term()}
Starts a supervisor with the given options.
This function is typically not invoked directly, instead it is invoked when using a dynamic_supervisor as a child of another supervisor.
If the supervisor is successfully spawned, this function returns
{ok, Pid}
, where Pid
is the PID of the supervisor. If the supervisor
is given a name and a process with the specified name already exists,
the function returns {error, {already_started, Pid}}
, where Pid
is the PID of that process.
{name, Name}
- registers the supervisor under the given name.{strategy, Strategy}
- the restart strategy option. The only supported
value is one_for_one
which means that no other child is
terminated if a child process terminates.{max_restarts, MaxRestarts}
- the maximum number of restarts allowed in
a time frame. Defaults to 3
.{max_seconds, MaxSeconds}
- the time frame in which max_restarts
applies.
Defaults to 5
.{max_children, MaxChildren}
- the maximum amount of children to be running
under this supervisor at the same time. When max_children
is
exceeded, start_child/2
returns {error, max_children}
. Defaults
to infinity
.{extra_arguments, ExtraArgs}
- arguments that are prepended to the arguments
specified in the child spec given to start_child/2
. Defaults to
an empty list.start_link(Module::module(), InitArg::term(), Opts::[start_option()]) -> {ok, pid()} | ignore | {error, term()}
Starts a module-based supervisor process with the given Module
and InitArg
.
init/1
callback will be invoked in the given
Module
, with InitArg
as its argument. The init/1
callback must return a
supervisor specification which can be created with the help of the init/1
function.
stop(Supervisor::pid() | atom() | {atom(), node()} | {global, atom()} | {via, module(), term()}) -> ok
Synchronously stops the given supervisor with the given Reason
.
It returns ok
if the supervisor terminates with the given
reason. If it terminates with another reason, the call exits.
normal
, shutdown
or
{shutdown, _}
, an error report is logged.
stop(Supervisor::pid() | atom() | {atom(), node()} | {global, atom()} | {via, module(), term()}, Reason::term()) -> ok
stop(Supervisor::pid() | atom() | {atom(), node()} | {global, atom()} | {via, module(), term()}, Reason::term(), Timeout::timeout()) -> ok
terminate_child(Supervisor::pid() | atom() | {atom(), node()} | {global, atom()} | {via, module(), term()}, Pid::pid()) -> ok | {error, not_found}
Terminates the given child identified by Pid
.
ok
. If there is no process with
the given PID, this function returns {error, not_found}
.
which_children(Supervisor::pid() | atom() | {atom(), node()} | {global, atom()} | {via, module(), term()}) -> [{undefined, pid() | restarting, worker | supervisor, [module()] | dynamic}]
Returns a list with information about all children.
Note that calling this function when supervising a large number of children under low memory conditions can cause an out of memory exception.
This function returns a list of tuples containing:Id
- it is always undefined
for dynamic supervisorsChild
- the PID of the corresponding child process or the
atom restarting
if the process is about to be restartedType
- worker
or supervisor
as defined in the child
specificationModules
- as defined in the child specificationGenerated by EDoc