Начальник поведение
Модуль поведения для реализации начальников.
Начальник — это процесс, который контролирует другие процессы, которые мы называем дочерними процессами. Начальники используются для построения иерархической структуры процессов, называемой деревом надзора. Деревья надзора обеспечивают отказоустойчивость и описывают, как запускаются и завершаются наши приложения.
Начальника можно запустить напрямую со списком дочерних процессов через start_link/2, или вы можете определить начальника на основе модуля, реализующего необходимые обратные вызовы. В разделах ниже используется start_link/2 для запуска начальников в большинстве примеров, но также есть отдельный раздел о начальниках на основе модулей.
Примеры
Для запуска начальника необходимо сначала определить дочерний процесс, который будет им контролироваться. В качестве примера определим GenServer, представляющий собой стек:
defmodule Stack do
use GenServer
def start_link(state) do
GenServer.start_link(__MODULE__, state, name: __MODULE__)
end
## Callbacks
@impl true
def init(stack) do
{:ok, stack}
end
@impl true
def handle_call(:pop, _from, [head | tail]) do
{:reply, head, tail}
end
@impl true
def handle_cast({:push, head}, tail) do
{:noreply, [head | tail]}
end
end
Стек — это небольшой оболочкой вокруг списков. Он позволяет поместить элемент на вершину стека, вставляя его в начало списка, и получить элемент с вершины стека с помощью сопоставления шаблонов.
Теперь мы можем запустить начальника, который будет запускать и контролировать наш процесс стека. Первый шаг — определить список спецификаций дочерних процессов, которые контролируют поведение каждого дочернего процесса. Каждая спецификация дочернего процесса — это карта, как показано ниже:
children = [
# The Stack is a child started via Stack.start_link([:hello])
%{
id: Stack,
start: {Stack, :start_link, [[:hello]]}
}
]
# Now we start the supervisor with the children and a strategy
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
# After started, we can query the supervisor for information
Supervisor.count_children(pid)
#=> %{active: 1, specs: 1, supervisors: 0, workers: 1}
Обратите внимание, что при запуске GenServer мы регистрируем его с именем Stack, что позволяет нам напрямую вызвать его и получить содержимое стека:
GenServer.call(Stack, :pop)
#=> :hello
GenServer.cast(Stack, {:push, :world})
#=> :ok
GenServer.call(Stack, :pop)
#=> :world
Однако в нашем сервере стека есть ошибка. Если мы вызываем :pop , а стек пуст, он аварийно завершится, так как не найдётся соответствующий вариант:
GenServer.call(Stack, :pop) ** (exit) exited in: GenServer.call(Stack, :pop, 5000)
К счастью, так как сервер контролируется начальником, начальник автоматически запустит новый, с начальным стеком [:hello]:
GenServer.call(Stack, :pop) #=> :hello
Начальники поддерживают разные стратегии; в примере выше мы выбрали :one_for_one. Кроме того, каждый начальник может иметь множество рабочих процессов и/или других начальников в качестве дочерних процессов, каждый со своей конфигурацией (как указано в разделе «Спецификация дочернего процесса»).
Остальная часть этого документа будет посвящена тому, как задаются спецификации дочерних процессов, как их можно запускать и останавливать, различным стратегиям надзора и прочему.
Спецификация дочернего процесса
Спецификация дочернего процесса описывает, как начальник запускает, завершает и перезапускает дочерние процессы.
Спецификация дочернего процесса — это карта, содержащая 6 элементов. Первые два ключа в следующем списке обязательны, остальные — необязательны:
:id— любой термин, используемый для идентификации спецификации дочернего процесса внутри начальника; по умолчанию совпадает с заданным модулем. В случае конфликта значений:id, начальник откажется от инициализации и потребует явные идентификаторы. Этот ключ обязателен.:start— кортеж с модулем-функцией-аргументами, которые должны быть вызваны для запуска дочернего процесса. Этот ключ обязателен.:restart— атом, определяющий, когда завершившийся дочерний процесс должен быть перезапущен (см. раздел «Значения перезапуска» ниже). Этот ключ необязателен и по умолчанию равен:permanent.:shutdown— целое число или атом, определяющий, как должен быть завершён дочерний процесс (см. раздел «Значения завершения» ниже). Этот ключ необязателен и по умолчанию равен5_000если тип:workerили:infinityесли тип:supervisor.:type— указывает, что дочерний процесс является:workerили:supervisor. Этот ключ необязателен и по умолчанию равен:worker.
Существует шестой ключ, :modules, который является необязательным и редко изменяется. Он устанавливается автоматически на основе значения :start.
Давайте разберёмся, за что отвечают опции :shutdown и :restart.
Значения завершения (:shutdown)
В опции :shutdown поддерживаются следующие значения завершения:
:brutal_kill— дочерний процесс безусловно и немедленно завершается с помощьюProcess.exit(child, :kill).любое целое число ≥ 0 — количество миллисекунд, которое начальник будет ждать завершения своих дочерних процессов после отправки сигнала
Process.exit(child, :shutdown). Если дочерний процесс не обрабатывает завершения, начальный сигнал:shutdownзавершит дочерний процесс немедленно. Если дочерний процесс обрабатывает завершения, у него есть заданное время на завершение. Если он не завершит работу в течение указанного времени, дочерний процесс безусловно завершается начальником с помощьюProcess.exit(child, :kill).:infinity— работает как целое число, за исключением того, что начальник будет ждать неопределённо долго завершения дочернего процесса. Если дочерний процесс является начальником, рекомендуемое значение —:infinity, чтобы дать начальнику и его дочерним процессам достаточно времени для завершения. Эта опция может быть использована с обычными рабочими процессами, но это не рекомендуется и требует особой осторожности. Если не использовать её осторожно, дочерний процесс никогда не завершится, что помешает завершению вашего приложения.
Значения перезапуска (:restart)
Опция :restart управляет тем, что начальник должен считать успешным завершением, а что нет. Если завершение успешное, начальник не будет перезапускать дочерний процесс. Если дочерний процесс аварийно завершился, начальник запустит новый.
В опции :restart поддерживаются следующие значения перезапуска:
:permanent— дочерний процесс всегда перезапускается.:temporary— дочерний процесс никогда не перезапускается, независимо от стратегии надзора: любое завершение (даже аварийное) считается успешным.:transient— дочерний процесс перезапускается только в случае аварийного завершения, то есть с причиной завершения, отличной от:normal,:shutdown, или{:shutdown, term}.
Для более подробного понимания причин завершения и их влияния, см. раздел «Причины завершения и перезапуски».
child_spec/1
При запуске начальника мы передаём список спецификаций дочерних процессов. Эти спецификации — это карты, которые указывают, как начальник должен запускать, останавливать и перезапускать каждый из своих дочерних процессов:
%{
id: Stack,
start: {Stack, :start_link, [[:hello]]}
}
В приведённой выше карте определён начальник с :id Stack , который запускается вызовом Stack.start_link([:hello]).
Однако указание спецификации дочернего процесса для каждого дочернего процесса в виде карты может быть весьма ошибочным, так как мы можем изменить реализацию стека и забыть обновить его спецификацию. Именно поэтому Elixir позволяет вам передавать кортеж с именем модуля и аргументом start_link вместо спецификации:
children = [
{Stack, [:hello]}
]
Начальник затем вызовет Stack.child_spec([:hello]) для получения спецификации дочернего процесса. Теперь модуль Stack отвечает за построение своей собственной спецификации, например, мы можем написать:
def child_spec(arg) do
%{
id: Stack,
start: {Stack, :start_link, [arg]}
}
end
К счастью для нас, use GenServer уже определяет Stack.child_spec/1 точно так же, как и выше. Если вам нужно настроить GenServer, вы можете передать опции непосредственно в use GenServer:
use GenServer, restart: :transient
Наконец, обратите внимание, что вы также можете просто передать модуль Stack как дочерний процесс:
children = [ Stack ]
Когда указано только имя модуля, это эквивалентно {Stack, []}. Заменив спецификацию карты на {Stack, [:hello]} или Stack, мы сохраняем спецификацию дочернего процесса внутри модуля Stack, используя реализацию по умолчанию, определённую в use GenServer. Теперь мы можем совместно использовать нашего Stack рабочего процесса с другими разработчиками, и они смогут добавить его непосредственно в своё дерево надзора, не беспокоясь о низкоуровневых деталях рабочего процесса.
В целом, спецификация дочернего процесса может быть одним из следующих:
- карта, представляющая саму спецификацию дочернего процесса — как описано в разделе «Спецификация дочернего процесса»
- кортеж с модулем в качестве первого элемента и аргументом запуска во втором — например,
{Stack, [:hello]}. В этом случае вызываетсяStack.child_spec([:hello])для получения спецификации дочернего процесса - модуль — например,
Stack. В этом случае вызываетсяStack.child_spec([])для получения спецификации дочернего процесса
Если вам нужно преобразовать спецификацию дочернего процесса типа кортеж или модуль в карту или изменить её, вы можете использовать функцию Supervisor.child_spec/2. Например, чтобы запустить стек с другим :id и значением :shutdown равным 10 секундам (10_000 миллисекунд):
children = [
Supervisor.child_spec({Stack, [:hello]}, id: MyStack, shutdown: 10_000)
]
Начальники на основе модулей
В примере выше начальник запускался путём передачи структуры надзора функции start_link/2. Однако начальники также могут создаваться путём явного определения модуля надзора:
defmodule MyApp.Supervisor do
# Automatically defines child_spec/1
use Supervisor
def start_link(init_arg) do
Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__)
end
@impl true
def init(_init_arg) do
children = [
{Stack, [:hello]}
]
Supervisor.init(children, strategy: :one_for_one)
end
end
Разница между этими двумя подходами заключается в том, что начальник на основе модуля даёт вам больший контроль над тем, как начальник инициализируется. Вместо вызова Supervisor.start_link/2 со списком дочерних процессов, которые автоматически инициализируются, мы вручную инициализировали дочерние процессы путём вызова Supervisor.init/2 внутри его обратного вызова init/1.
use Supervisor также определяет функцию child_spec/1, которая позволяет нам запустить MyApp.Supervisor в качестве дочернего процесса другого начальника или в верхней части вашего дерева надзора, как в примере:
children = [ MyApp.Supervisor ] Supervisor.start_link(children, strategy: :one_for_one)
Общее правило состоит в том, чтобы использовать начальник без модуля обратного вызова только в верхней части вашего дерева надзора, как правило, в обратном вызове Application.start/2. Мы рекомендуем использовать начальники на основе модулей для любого другого начальника в вашем приложении, чтобы они могли работать в качестве дочернего процесса другого начальника в дереве. Модуль child_spec/1, генерируемый автоматически функцией Supervisor, может быть настроен с помощью следующих опций:
-
:id— идентификатор спецификации дочернего процесса, по умолчанию — текущий модуль -
:restart— когда начальник должен быть перезапущен, по умолчанию:permanent
Аннотация @doc , немедленно предшествующая use Supervisor , будет прикреплена к сгенерированной функции child_spec/1.
start_link/2, init/2 и стратегии
До сих пор мы запускали надзорный процесс, передавая единственного ребёнка как кортеж, а также стратегию под названием :one_for_one:
children = [
{Stack, [:hello]}
]
Supervisor.start_link(children, strategy: :one_for_one)
или изнутри обратного вызова init/1:
children = [
{Stack, [:hello]}
]
Supervisor.init(children, strategy: :one_for_one)
Первый аргумент, переданный функциям start_link/2 и init/2, представляет собой список спецификаций дочерних процессов, как определено в разделе "child_spec/1" выше.
Второй аргумент — список ключевых слов опций:
:strategy— опция стратегии надзора. Она может быть:one_for_one,:rest_for_oneили:one_for_all. Требуется. См. раздел "Стратегии".:max_restarts— максимальное количество перезапусков, разрешенных в течение определённого временного интервала. По умолчанию3.:max_seconds— временной интервал, в котором действует:max_restarts. По умолчанию5.:name— имя для регистрации процесса надзорщика. Допустимые значения описаны в разделе "Регистрация имени" в документации дляGenServer. Необязательно.
Стратегии
Надзорные процессы поддерживают различные стратегии надзора (через опцию :strategy, как показано выше):
:one_for_one— если дочерний процесс завершается, перезапускается только этот процесс.:one_for_all— если дочерний процесс завершается, все другие дочерние процессы завершаются, а затем все дочерние процессы (включая завершившийся) перезапускаются.:rest_for_one— если дочерний процесс завершается, завершается завершившийся дочерний процесс и все остальные дочерние процессы, запущенные после него, и они перезапускаются.
В приведенном выше примере завершение процесса относится к неудачному завершению, которое определяется опцией :restart.
Для динамического надзора за дочерними процессами см. DynamicSupervisor.
Регистрация имени
Надзорный процесс подчиняется тем же правилам регистрации имен, что и GenServer. Подробнее об этих правилах см. в документации для GenServer.
Запуск и завершение
При запуске надзорный процесс проходит по всем спецификациям дочерних процессов и запускает каждый процесс в порядке их определения. Это делается с помощью вызова функции, определенной под ключом :start в спецификации дочернего процесса, и по умолчанию она равна start_link/1.
Затем вызывается функция start_link/1 (или пользовательская) для каждого дочернего процесса. Функция start_link/1 должна возвращать {:ok, pid}, где pid — идентификатор процесса нового процесса, связанного с надзорным процессом. Дочерний процесс обычно начинает свою работу, выполняя обратный вызов init/1. Как правило, обратный вызов init используется для инициализации и настройки дочернего процесса.
Процесс завершения происходит в обратном порядке.
При завершении работы надзорный процесс завершает все дочерние процессы в обратном порядке их перечисления. Завершение происходит путём отправки сигнала выхода завершения, через Process.exit(child_pid, :shutdown), дочернему процессу, а затем ожидания интервала времени, пока дочерний процесс завершится. Этот интервал по умолчанию составляет 5000 миллисекунд. Если дочерний процесс не завершается в этот интервал, надзорный процесс резко завершает его с причиной :kill. Время завершения можно настроить в спецификации дочернего процесса, что подробно описано в следующем разделе.
Если дочерний процесс не обрабатывает выходы, он завершится немедленно при получении первого сигнала выхода. Если дочерний процесс обрабатывает выходы, вызывается обратный вызов terminate, и дочерний процесс должен завершиться в разумный интервал времени, прежде чем надзорный процесс резко завершит его.
Другими словами, если важно, чтобы процесс очистил за собой, когда ваше приложение или дерево надзора завершается, этот процесс должен обрабатывать выходы, и его спецификация дочернего процесса должна указать соответствующее значение :shutdown , гарантируя его завершение в разумный интервал времени.
Причины выхода и перезапуски
Надзорный процесс перезапускает дочерний процесс в зависимости от его конфигурации :restart. Например, когда :restart установлено в :transient, надзорный процесс не перезапускает дочерний процесс, если он завершается с причиной :normal, :shutdown или {:shutdown, term}.
Итак, можно спросить: какую причину выхода мне следует выбрать при выходе? Существует три варианта:
:normal— в таких случаях выход не регистрируется, перезапуск в транзиентном режиме отсутствует, и связанные процессы не завершаются.:shutdownили{:shutdown, term}— в таких случаях выход не регистрируется, перезапуск в транзиентном режиме отсутствует, и связанные процессы завершаются с той же причиной, если они не обрабатывают выходы.любое другое значение — в таких случаях выход регистрируется, перезапуски в транзиентном режиме присутствуют, и связанные процессы завершаются с той же причиной, если они не обрабатывают выходы.
Обратите внимание, что надзорный процесс, достигший максимальной интенсивности перезапусков, завершается с причиной :shutdown. В этом случае надзорный процесс будет перезапущен только в том случае, если в его спецификации дочернего процесса была задана опция :restart со значением :permanent (по умолчанию).
Сводка
Типы
- child_spec()
Спецификация надзорного процесса
- init_option()
Опции, переданные
start_link/2иinit/2- name()
Имя надзорщика
- on_start()
Значения возвращаемые функциями
start_link- on_start_child()
Значения возвращаемые функциями
start_child- option()
Значения опций, используемые функциями
start*- strategy()
Поддерживаемые стратегии
- supervisor()
Ссылка на надзорщика
Функции
- child_spec(module_or_map, overrides)
Создаёт и переопределяет спецификацию дочернего процесса.
- count_children(supervisor)
Возвращает карту, содержащую значения счётчиков для заданного надзорщика.
- delete_child(supervisor, child_id)
Удаляет спецификацию дочернего процесса, идентифицированного по
child_id.- init(children, options)
Получает список
childrenдля инициализации и наборoptions.- restart_child(supervisor, child_id)
Перезапускает дочерний процесс, идентифицированный по
child_id.- start_child(supervisor, child_spec)
Добавляет спецификацию дочернего процесса к
supervisorи запускает этот дочерний процесс.- start_link(children, options)
Запускает надзорный процесс с заданными дочерними процессами.
- start_link(module, init_arg, options \\ [])
Запускает модульный процесс надзорщика с заданными
moduleиinit_arg.- stop(supervisor, reason \\ :normal, timeout \\ :infinity)
Синхронно останавливает заданный надзорный процесс с заданной
reason.- terminate_child(supervisor, child_id)
Завершает указанный дочерний процесс, идентифицированный по
child_id.- which_children(supervisor)
Возвращает список с информацией обо всех дочерних процессах данного надзорщика.
Обратные вызовы
- init(init_arg)
Вызываемый обратный вызов для запуска надзорщика и во время обновлений горячего кода.
Типы
child()
Характеристики
child() :: pid() | :undefined
child_spec()
Характеристики
child_spec() :: %{
:id => atom() | term(),
:start => {module(), atom(), [term()]},
optional(:restart) => :permanent | :transient | :temporary,
optional(:shutdown) => timeout() | :brutal_kill,
optional(:type) => :worker | :supervisor,
optional(:modules) => [module()] | :dynamic
} Спецификация надзирателя
init_option()
Характеристики
init_option() ::
{:strategy, strategy()}
| {:max_restarts, non_neg_integer()}
| {:max_seconds, pos_integer()} Параметры, задаваемые для start_link/2 и init/2
name()
Характеристики
name() :: atom() | {:global, term()} | {:via, module(), term()} Имя надзирателя
on_start()
Характеристики
on_start() ::
{:ok, pid()}
| :ignore
| {:error, {:already_started, pid()} | {:shutdown, term()} | term()} Возвращаемые значения функций start_link
on_start_child()
Характеристики
on_start_child() ::
{:ok, child()}
| {:ok, child(), info :: term()}
| {:error, {:already_started, child()} | :already_present | term()} Возвращаемые значения функций start_child
option()
Характеристики
option() :: {:name, name()} Значения параметров, используемые функциями start*
strategy()
Характеристики
strategy() :: :one_for_one | :one_for_all | :rest_for_one
Поддерживаемые стратегии
supervisor()
Характеристики
supervisor() :: pid() | name() | {atom(), node()} Ссылка на надзирателя
Функции
child_spec(module_or_map, overrides)
Спецификации
child_spec(child_spec() | {module(), arg :: term()} | module(), keyword()) ::
child_spec() Создаёт и переопределяет спецификацию дочернего процесса.
Аналогично start_link/2 и init/2, ожидает module, {module, arg} или карту в качестве спецификации дочернего процесса. Если предоставлен модуль, спецификация извлекается вызовом module.child_spec(arg).
После извлечения спецификации дочернего процесса, поля из overrides напрямую применяются к спецификации. Если overrides содержит ключи, которые не соответствуют ни одному полю спецификации дочернего процесса, генерируется ошибка.
См. раздел "Спецификация дочернего процесса" в документации модуля для получения всех доступных ключей для переопределения.
Примеры
Эта функция часто используется для установки параметра :id, когда один и тот же модуль нужно запускать несколько раз в дереве наблюдения:
Supervisor.child_spec({Agent, fn -> :ok end}, id: {Agent, 1})
#=> %{id: {Agent, 1},
#=> start: {Agent, :start_link, [fn -> :ok end]}} count_children(supervisor)
Спецификации
count_children(supervisor()) :: %{
specs: non_neg_integer(),
active: non_neg_integer(),
supervisors: non_neg_integer(),
workers: non_neg_integer()
} Возвращает карту, содержащую значения подсчёта для данного надсмотрщика.
Карта содержит следующие ключи:
:specs- общее количество дочерних процессов, живых или умерших:active- количество активно работающих дочерних процессов, управляемых этим надсмотрщиком:supervisors- количество всех надсмотрщиков, независимо от того, живы ли эти дочерние надсмотрщики:workers- количество всех рабочих процессов, независимо от того, живы ли эти дочерние рабочие процессы
delete_child(supervisor, child_id)
Спецификации
delete_child(supervisor(), term()) :: :ok | {:error, error}
when error: :not_found | :running | :restarting Удаляет спецификацию дочернего процесса, идентифицированную по child_id.
Соответствующий дочерний процесс не должен выполняться; используйте terminate_child/2 для его завершения, если он работает.
В случае успеха эта функция возвращает :ok. Эта функция может возвращать ошибку с соответствующей кортежем ошибки, если child_id не найдена или текущий процесс выполняется или перезапускается.
init(children, options)
Спецификации
init([:supervisor.child_spec() | {module(), term()} | module()], [init_option()]) ::
{:ok, tuple()} Получает список children для инициализации и набор options.
Обычно вызывается в конце обратного вызова init/1 надсмотрщиков на основе модулей. См. разделы "Надсмотрщики на основе модулей" и "start_link/2, init/2 и стратегии" в документации модуля для получения дополнительной информации.
Эта функция возвращает кортеж, содержащий флаги надсмотрщика и спецификации дочерних процессов.
Примеры
def init(_init_arg) do
children = [
{Stack, [:hello]}
]
Supervisor.init(children, strategy: :one_for_one)
end
Параметры
:strategy- параметр стратегии наблюдения. Может быть:one_for_one,:rest_for_one, или:one_for_all:max_restarts- максимальное количество перезапусков, разрешённых в заданном интервале времени. По умолчанию3.:max_seconds- интервал времени в секундах, в котором применяется:max_restarts. По умолчанию5.
Параметр :strategy обязателен и по умолчанию позволяет максимум 3 перезапуска в течение 5 секунд. Обратитесь к Supervisor модулю для подробного описания доступных стратегий.
restart_child(supervisor, child_id)
Спецификации
restart_child(supervisor(), term()) ::
{:ok, child()} | {:ok, child(), term()} | {:error, error}
when error: :not_found | :running | :restarting | term() Перезапускает дочерний процесс, идентифицированный по child_id.
Спецификация дочернего процесса должна существовать, и соответствующий дочерний процесс не должен выполняться.
Обратите внимание, что для временных дочерних процессов спецификация дочернего процесса автоматически удаляется при завершении дочернего процесса, и поэтому такие дочерние процессы перезапустить нельзя.
Если функция запуска дочернего процесса возвращает {:ok, child} или {:ok, child, info}, PID добавляется к надсмотрщику, и эта функция возвращает то же значение.
Если функция запуска дочернего процесса возвращает :ignore, PID остаётся :undefined, и эта функция возвращает {:ok, :undefined}.
Эта функция может возвращать ошибку с соответствующей кортежем ошибки, если child_id не найдена или текущий процесс выполняется или перезапускается.
Если функция запуска дочернего процесса возвращает кортеж ошибки или ошибочное значение или завершается с ошибкой, эта функция возвращает {:error, error}.
start_child(supervisor, child_spec)
Спецификации
start_child(
supervisor(),
:supervisor.child_spec() | {module(), term()} | module()
) :: on_start_child() Добавляет спецификацию дочернего процесса к supervisor и запускает этот дочерний процесс.
child_spec должна быть валидной спецификацией дочернего процесса. Дочерний процесс будет запущен в соответствии с определением в спецификации дочернего процесса.
Если спецификация дочернего процесса с указанным идентификатором уже существует, child_spec отбрасывается, и эта функция возвращает ошибку с :already_started или :already_present соответственно, если соответствующий дочерний процесс выполняется или нет.
Если функция запуска дочернего процесса возвращает {:ok, child} или {:ok, child, info}, то спецификация дочернего процесса и PID добавляются к надсмотрщику, и эта функция возвращает то же значение.
Если функция запуска дочернего процесса возвращает :ignore, спецификация дочернего процесса добавляется к надсмотрщику, PID устанавливается в :undefined, и эта функция возвращает {:ok, :undefined}.
Если функция запуска дочернего процесса возвращает кортеж ошибки или ошибочное значение или завершается с ошибкой, спецификация дочернего процесса отбрасывается, и эта функция возвращает {:error, error}, где error — термин, содержащий информацию об ошибке и спецификации дочернего процесса.
start_link(children, options)
Спецификации
start_link([:supervisor.child_spec() | {module(), term()} | module()], [
option() | init_option()
]) ::
{:ok, pid()}
| {:error, {:already_started, pid()} | {:shutdown, term()} | term()} start_link(module(), term()) :: on_start()
Запускает надсмотрщика с заданными дочерними процессами.
Children — список модулей, кортежей из двух элементов (модуль и аргументы) или карта со спецификацией дочернего процесса. Стратегия должна быть указана через параметр :strategy. См. "start_link/2, init/2 и стратегии" для примеров и других параметров.
Параметры также могут использоваться для регистрации имени надсмотрщика. Поддерживаемые значения описаны в разделе "Регистрация имени" в документации модуля GenServer.
Если надсмотрщик и его дочерние процессы успешно запущены (если функция запуска каждого дочернего процесса возвращает {:ok, child}, {:ok, child, info}, или :ignore), эта функция возвращает {:ok, pid}, где pid — PID надсмотрщика. Если надсмотрщику задано имя и процесс с указанным именем уже существует, функция возвращает {:error, {:already_started, pid}}, где pid — PID этого процесса.
Если функция запуска любого дочернего процесса завершается ошибкой или возвращает кортеж ошибки или ошибочное значение, надсмотрщик сначала завершает все уже запущенные дочерние процессы с причиной :shutdown, а затем завершает сам себя и возвращает {:error, {:shutdown, reason}}.
Обратите внимание, что надсмотрщик, запущенный с помощью этой функции, связан с родительским процессом и завершается не только при сбоях, но и если родительский процесс завершается с причиной :normal.
start_link(module, init_arg, options \\ [])
Спецификации
start_link(module(), term(), [option()]) :: on_start()
Запускает процесс надсмотрщика на основе модуля с заданным module и init_arg.
Для запуска надсмотрщика будет вызван обратный вызов init/1 в заданном module, с init_arg в качестве аргумента. Обратный вызов init/1 должен вернуть спецификацию надсмотрщика, которую можно создать с помощью функции init/2.
Если обратный вызов init/1 возвращает :ignore, эта функция также возвращает :ignore и надсмотрщик завершается с причиной :normal. Если он завершается с ошибкой или возвращает неправильное значение, эта функция возвращает {:error, term} , где term — термин с информацией об ошибке, и надсмотрщик завершается с причиной term.
Параметр :name также может быть задан для регистрации имени надсмотрщика, поддерживаемые значения описаны в разделе "Регистрация имени" в документации модуля GenServer.
stop(supervisor, reason \\ :normal, timeout \\ :infinity)
Спецификации
stop(supervisor(), reason :: term(), timeout()) :: :ok
Синхронно останавливает данный надсмотрщик с указанной reason.
Возвращает :ok если надсмотрщик завершается с указанной причиной. Если завершается с другой причиной, вызов завершается.
Эта функция сохраняет семантику OTP в отношении отчётов об ошибках. Если причина отличается от :normal, :shutdown или {:shutdown, _}, создаётся отчёт об ошибке.
terminate_child(supervisor, child_id)
Характеристики
terminate_child(supervisor(), term()) :: :ok | {:error, :not_found} Прерывает указанного дочернего процесса, идентифицированного по child_id.
Процесс прерывается, если он существует. Спецификация дочернего процесса сохраняется, если он не временный.
Процесс дочернего процесса, не являющийся временным, может быть позже перезапущен диспетчером. Дочерний процесс также может быть перезапущен явно, вызвав restart_child/2. Используйте delete_child/2 для удаления спецификации дочернего процесса.
При успешном выполнении функция возвращает :ok. Если для данного идентификатора дочернего процесса нет спецификации, функция возвращает {:error, :not_found}.
which_children(supervisor)
Характеристики
which_children(supervisor()) :: [
{term() | :undefined, child() | :restarting, :worker | :supervisor,
:supervisor.modules()}
] Возвращает список с информацией обо всех дочерних процессах данного диспетчера.
Обратите внимание, что вызов этой функции при наблюдении за большим количеством дочерних процессов в условиях низкой памяти может вызвать исключение из-за недостатка памяти.
Функция возвращает список кортежей {id, child, type, modules}, где:
id- как определено в спецификации дочернего процесса:restarting- PID соответствующего дочернего процесса,:restartingесли процесс готов к перезапуску, или:undefinedесли такого процесса нетtype-:workerили:supervisor, как указано в спецификации дочернего процессаmodules- как указано в спецификации дочернего процесса
Обработчики
init(init_arg)
Характеристики
init(init_arg :: term()) ::
{:ok, {:supervisor.sup_flags(), [:supervisor.child_spec()]}} | :ignore Обработчик, вызываемый для запуска диспетчера и во время горячих обновлений кода.
Разработчики обычно вызывают Supervisor.init/2 в конце своего обработчика init, чтобы вернуть правильные флаги управления.
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.10.4/Supervisor.html