global_supervisor v0.1.0 GlobalSupervisor behaviour
A supervisor that dynamically distributes children across the cluster.
A GlobalSupervisor
is like a DynamicSupervisor
that coordinates with other
GlobalSupervisors registered with the same name in the cluster to dynamically
distribute children across the cluster.
A GlobalSupervisor
has the same API and behaviour of a DynamicSupervisor
with some minor differences to provide distributed functionality.
When you start a child using start_child/2
, global supervisor uses a
consistent hash algorithm to decide on which node it should be started.
When a node goes down, all children running on that node will be
redistributed on remaining nodes. When a new node is added to the cluster
global supervisor by default automatically rebalances distribution of
running children.
In case of a network split each partition restarts children running on the
other part assuming that part is down. Once the partition is healed,
children will be rebalanced again, but rebalancing might lead to some children
being started again on the same node which they started on initially.
Also when auto balancing is disabled, a healed netsplit might have multiple
instances of the same child running on two or more nodes. To prevent two
instances of the same child stay running after a net split heals, you need
to register each child process with a unique name. Local names will only
prevent running multiple instances of a child on a single node, you can
use :global
registry or any other distributed registry to prevent running
multiple instances of a child across the cluster.
temporary
children once started, won't be rebalanced or moved in the cluster.
You can change consistent hash algorithm, and disable auto balancing feature using init options.
Link to this section Summary
Types
Child specification
Options given to start_link/2
and init/1
Option values used by the start*
functions
Options used by the start*
functions
Supported strategies
The supervisor flags returned on init
Functions
Returns a specification to start a global supervisor under a supervisor
Same as DynamicSupervisor.count_children/1
with accumulated results of all global supervisors
registered with the same name in the cluster
Receives a set of options
that initializes a global supervisor
Default :locator
used to locate where to start/move a child
Scans all the local children and moves the ones that don't belong to the
current node based on the result of :locater
function
Dynamically starts a child under one of the global supervisor instances registered with the same name in the cluster
Starts a supervisor with the given options
Starts a module-based supervisor process with the given module
and arg
Terminates the given child identified by pid
. It can be a child running on another node
Same as DynamicSupervisor.which_children/1
with accumulated results of all global supervisors
registered with the same name in the cluster
Callbacks
Callback invoked to start the supervisor and during hot code upgrades
Link to this section Types
child_spec()
Child specification
init_option()
init_option() ::
{:strategy, strategy()}
| {:max_restarts, non_neg_integer()}
| {:max_seconds, pos_integer()}
| {:max_children, non_neg_integer() | :infinity}
| {:extra_arguments, [term()]}
| {:auto_balance, boolean()}
| {:locator, (tuple(), [atom()] -> atom())}
init_option() :: {:strategy, strategy()} | {:max_restarts, non_neg_integer()} | {:max_seconds, pos_integer()} | {:max_children, non_neg_integer() | :infinity} | {:extra_arguments, [term()]} | {:auto_balance, boolean()} | {:locator, (tuple(), [atom()] -> atom())}
Options given to start_link/2
and init/1
option()
option() :: {:name, Supervisor.name()} | init_option()
option() :: {:name, Supervisor.name()} | init_option()
Option values used by the start*
functions
options()
options() :: [option(), ...]
options() :: [option(), ...]
Options used by the start*
functions
strategy()
strategy() :: :one_for_one
strategy() :: :one_for_one
Supported strategies
sup_flags()
sup_flags() :: %{
strategy: strategy(),
intensity: non_neg_integer(),
period: pos_integer(),
max_children: non_neg_integer() | :infinity,
extra_arguments: [term()],
auto_balance: boolean(),
locator: (tuple(), [atom()] -> atom())
}
sup_flags() :: %{ strategy: strategy(), intensity: non_neg_integer(), period: pos_integer(), max_children: non_neg_integer() | :infinity, extra_arguments: [term()], auto_balance: boolean(), locator: (tuple(), [atom()] -> atom()) }
The supervisor flags returned on init
Link to this section Functions
child_spec(opts)
Returns a specification to start a global supervisor under a supervisor.
See Supervisor
.
count_children(supervisor)
count_children(Supervisor.supervisor()) :: %{
specs: non_neg_integer(),
active: non_neg_integer(),
supervisors: non_neg_integer(),
workers: non_neg_integer()
}
count_children(Supervisor.supervisor()) :: %{ specs: non_neg_integer(), active: non_neg_integer(), supervisors: non_neg_integer(), workers: non_neg_integer() }
Same as DynamicSupervisor.count_children/1
with accumulated results of all global supervisors
registered with the same name in the cluster.
init(options)
init([init_option()]) :: {:ok, sup_flags()}
init([init_option()]) :: {:ok, sup_flags()}
Receives a set of options
that initializes a global supervisor.
It accepts the same options as DynamicSupervisor.init/1
with these two
additional options:
:locator
- a function that accepts child_spec as a tuple and a list of nodes where childs can be placed on. This function should return one of the nodes in the given nodes list, and is used by the supervisor to decide where to start/move a child in the cluster. Defaults tolocate/2
.:auto_balance
- whether to automatically rebalance children when a new node is added to the cluster. Defaults totrue
.
locate(child_spec, nodes)
locate(child_spec(), [node()]) :: node()
locate(child_spec(), [node()]) :: node()
Default :locator
used to locate where to start/move a child.
It uses :erlang.phash2/2
to consistently select a node for the given child_spec.
rebalance(supervisor)
rebalance(Supervisor.supervisor()) :: :ok
rebalance(Supervisor.supervisor()) :: :ok
Scans all the local children and moves the ones that don't belong to the
current node based on the result of :locater
function.
A global supervisor by default rebalances itself when cluster topology changes,
but if you disable :auto_balance
, this function can be used to manually
rebalance children on each node.
start_child(supervisor, child_spec)
start_child(
Supervisor.supervisor(),
Supervisor.child_spec() | {module(), term()} | module()
) :: DynamicSupervisor.on_start_child()
start_child( Supervisor.supervisor(), Supervisor.child_spec() | {module(), term()} | module() ) :: DynamicSupervisor.on_start_child()
Dynamically starts a child under one of the global supervisor instances registered with the same name in the cluster.
It uses locate/2
as default :locator
to decide where to start the child.
:locator
can be changed in init options.
start_link(options)
start_link(options()) :: Supervisor.on_start()
start_link(options()) :: Supervisor.on_start()
Starts a supervisor with the given options.
The :strategy
is a required option and the currently supported
value is :one_for_one
. The remaining options can be found in the
init/1
docs.
The :name
option is used to group global supervisors with the same name
in the cluster together, and it has to be a local name, and if not provided
GlobalSupervisor
will be used.
start_link(mod, init_arg, opts \\ [])
start_link(module(), term(), GenServer.options()) :: Supervisor.on_start()
start_link(module(), term(), GenServer.options()) :: Supervisor.on_start()
Starts a module-based supervisor process with the given module
and arg
.
stop(supervisor, reason \\ :normal, timeout \\ :infinity)
stop(Supervisor.supervisor(), reason :: term(), timeout()) :: :ok
stop(Supervisor.supervisor(), reason :: term(), timeout()) :: :ok
Same as DynamicSupervisor.stop/3
.
terminate_child(supervisor, pid)
terminate_child(Supervisor.supervisor(), pid()) :: :ok | {:error, :not_found}
terminate_child(Supervisor.supervisor(), pid()) :: :ok | {:error, :not_found}
Terminates the given child identified by pid
. It can be a child running on another node.
If successful, this function returns :ok
. If there is no process with
the given PID, this function returns {:error, :not_found}
.
which_children(supervisor)
which_children(Supervisor.supervisor()) :: [
{:undefined, pid() | :restarting, :worker | :supervisor,
:supervisor.modules()}
]
which_children(Supervisor.supervisor()) :: [ {:undefined, pid() | :restarting, :worker | :supervisor, :supervisor.modules()} ]
Same as DynamicSupervisor.which_children/1
with accumulated results of all global supervisors
registered with the same name in the cluster.
Link to this section Callbacks
init(init_arg)
Callback invoked to start the supervisor and during hot code upgrades.
Developers typically invoke GlobalSupervisor.init/1
at the end of
their init callback to return the proper supervision flags.