Supervisor поведение
Модуль поведения для реализации супервайзеров.
Супервайзер — это процесс, который контролирует другие процессы, которые мы называем дочерними процессами. Супервайзеры используются для построения иерархической структуры процессов, называемой деревом наблюдения. Деревья наблюдения обеспечивают отказоустойчивость и инкапсулируют, как запускаются и завершаются наши приложения.
Супервайзер можно запустить напрямую со списком спецификаций дочерних процессов с помощью start_link/2, или же вы можете определить супервайзер на основе модуля, реализующего необходимые обратные вызовы. В разделах ниже используется start_link/2 для запуска супервайзеров в большинстве примеров, но также есть отдельный раздел для супервайзеров на основе модулей.
Примеры
Для запуска супервайзера необходимо сначала определить дочерний процесс, который будет контролироваться. В качестве примера мы определим GenServer, универсальный сервер, который хранит счётчик. Другие процессы могут отправлять сообщения в этот процесс для чтения счётчика и увеличения его значения.
Примечание: на практике вы не определяли бы счётчик как GenServer. Вместо этого, если вам нужен счётчик, вы передадите его как входные и выходные данные в функции, которые его используют. Причина, по которой мы выбрали счётчик в этом примере, заключается в его простоте, так как это позволяет нам сосредоточиться на том, как работают супервайзеры.
defmodule Counter do
use GenServer
def start_link(arg) when is_integer(arg) do
GenServer.start_link(__MODULE__, arg, name: __MODULE__)
end
## Callbacks
@impl true
def init(counter) do
{:ok, counter}
end
@impl true
def handle_call(:get, _from, counter) do
{:reply, counter, counter}
end
def handle_call({:bump, value}, _from, counter) do
{:reply, counter, counter + value}
end
end
Counter получает аргумент в start_link. Этот аргумент передаётся в обратный вызов init/1, который становится начальным значением счётчика. Наш счётчик обрабатывает две операции (известные как вызовы): :get, для получения текущего значения счётчика, и :bump, которая увеличивает счётчик на заданное value значение и возвращает старое значение счётчика.
Теперь мы можем запустить супервайзер, который запустит и будет контролировать наш процесс счётчика. Первый шаг — определить список спецификаций дочерних процессов, которые контролируют поведение каждого дочернего процесса. Каждая спецификация дочернего процесса представляет собой карту, как показано ниже:
children = [
# The Counter is a child started via Counter.start_link(0)
%{
id: Counter,
start: {Counter, :start_link, [0]}
}
]
# 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 мы регистрируем его с именем Counter через опцию name: __MODULE__. Это позволяет нам вызывать его напрямую и получить его значение:
GenServer.call(Counter, :get)
#=> 0
GenServer.cast(Counter, {:bump, 3})
#=> 0
GenServer.call(Counter, :get)
#=> 3
Однако в нашем сервере счётчика есть ошибка. Если мы вызовем :bump с нечисловым значением, он аварийно завершится:
GenServer.call(Counter, {:bump, "oops"})
** (exit) exited in: GenServer.call(Counter, {:bump, "oops"}, 5000)
К счастью, поскольку сервер контролируется супервайзером, супервайзер автоматически запустит новый, сбросив значение обратно к начальному значению 0:
GenServer.call(Counter, :get) #=> 0
Супервайзеры поддерживают разные стратегии; в примере выше мы выбрали :one_for_one. Кроме того, каждый супервайзер может иметь множество рабочих процессов и/или других супервайзеров в качестве дочерних, и каждый из них имеет собственную конфигурацию (как указано в разделе "Спецификация дочернего процесса").
Остальная часть этого документа будет посвящена тому, как задаются дочерние процессы, как они могут быть запущены и остановлены, различным стратегиям наблюдения и многому другому.
Спецификация дочернего процесса
Спецификация дочернего процесса описывает, как супервайзер запускает, завершает и перезапускает дочерние процессы.
Спецификация дочернего процесса — это карта, содержащая до 6 элементов. Первые два ключа в следующем списке являются обязательными, а остальные — необязательными:
:id— любой термин, используемый для идентификации спецификации дочернего процесса внутри супервайзера; по умолчанию — указанный модуль. Этот ключ является обязательным. В случае конфликта значений:id, супервайзер откажется от инициализации и потребует явных идентификаторов. Однако это не относится к динамическим супервайзерам.:start— кортеж с модулем-функцией-аргументами, которые вызываются для запуска дочернего процесса. Этот ключ является обязательным.:restart— атом, определяющий, когда завершённый дочерний процесс должен быть перезапущен (см. раздел "Значения перезапуска" ниже). Этот ключ является необязательным и по умолчанию равен:permanent.:shutdown— целое число или атом, определяющий, как дочерний процесс должен завершаться (см. раздел "Значения завершения" ниже). Этот ключ является необязательным и по умолчанию равен5_000если тип:worker, или:infinityесли тип:supervisor.:type— указывает, что дочерний процесс является:workerили:supervisor. Этот ключ является необязательным и по умолчанию равен:worker.:modules— список модулей, используемых механизмами горячей замены кода для определения, какие процессы используют определённые модули. Обычно он устанавливается в модуль обратного вызова поведения, такого какGenServer,Supervisor, и т. п. Он устанавливается автоматически на основе значения: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: Counter,
start: {Counter, :start_link, [0]}
}
В представленной выше карте определён дочерний процесс с :id Counter, который запускается путём вызова Counter.start_link(0).
Однако определение спецификации дочернего процесса для каждого дочернего процесса в виде карты может быть достаточно подвержено ошибкам, так как мы можем изменить реализацию Counter и забыть обновить его спецификацию. Именно поэтому Elixir позволяет передавать кортеж с именем модуля и аргументом start_link вместо спецификации:
children = [
{Counter, 0}
]
Супервайзер вызовет Counter.child_spec(0) для получения спецификации дочернего процесса. Теперь модуль Counter отвечает за создание собственной спецификации. Например, мы можем написать:
def child_spec(arg) do
%{
id: Counter,
start: {Counter, :start_link, [arg]}
}
end
К счастью для нас, use GenServer уже определяет Counter.child_spec/1 точно так же, как выше, поэтому вам не нужно писать определение самостоятельно. Если вы хотите настроить автоматически сгенерированную функцию child_spec/1, вы можете передать опции напрямую в use GenServer:
use GenServer, restart: :transient
Наконец, также возможно просто передать модуль Counter как дочерний процесс:
children = [ Counter ]
При передаче только имени модуля это эквивалентно {Counter, []}, которое в нашем случае было бы неверным, поэтому мы всегда явно передаём начальный счётчик.
Заменив спецификацию дочернего процесса на {Counter, 0}, мы сохраняем её в инкапсулированном виде в модуле Counter . Теперь мы можем поделиться реализацией Counter с другими разработчиками, и они могут добавить её напрямую в своё дерево наблюдения, не беспокоясь о низкоуровневых деталях счётчика.
В целом, спецификация дочернего процесса может быть одной из следующих:
карта, представляющая саму спецификацию дочернего процесса — как описано в разделе "Спецификация дочернего процесса"
кортеж с модулем в качестве первого элемента и аргументом запуска во втором — например,
{Counter, 0}. В этом случае вызываетсяCounter.child_spec(0), чтобы получить спецификацию дочернего процессамодуль — например,
Counter. В этом случае вызываетсяCounter.child_spec([]), что неверно для счётчика, но полезно во многих других случаях, особенно когда вы хотите передать список опций дочернему процессу
Если вам нужно преобразовать кортеж {module, arg} или спецификацию дочернего процесса в виде модуля в спецификацию дочернего процесса или изменить саму спецификацию дочернего процесса, вы можете использовать функцию Supervisor.child_spec/2. Например, для запуска счётчика с другим :id и значением :shutdown в 10 секунд (10 000 миллисекунд):
children = [
Supervisor.child_spec({Counter, 0}, id: MyCounter, shutdown: 10_000)
]
Стратегии и опции супервайзера
До сих пор мы запускали супервайзер, передавая единственный дочерний процесс в виде кортежа, а также стратегию, называемую :one_for_one:
children = [
{Counter, 0}
]
Supervisor.start_link(children, strategy: :one_for_one)
Первый аргумент, переданный в start_link/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_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 = [
{Counter, 0}
]
Supervisor.init(children, strategy: :one_for_one)
end
end
Разница между этими подходами заключается в том, что модульно-базированный контролёр даёт вам больший контроль над инициализацией контролёра. Вместо вызова Supervisor.start_link/2 со списком спецификаций дочерних процессов, которые автоматически инициализируются, мы вручную инициализируем дочерние процессы, вызывая Supervisor.init/2 внутри его обратного вызова init/1. Supervisor.init/2 принимает те же параметры :strategy, :max_restarts, и :max_seconds что и start_link/2.
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 в спецификации дочернего процесса, и по умолчанию соответствует 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()
Процесс-потомок.
- child_spec()
Спецификация процесса-потомка для надзирателя.
- init_option()
Параметры, переданные функциям
start_link/2иinit/2- name()
Имя надзирателя
- on_start()
Возвращаемые значения функций
start_link- on_start_child()
Возвращаемые значения функций
start_child- option()
Значения параметров, используемые функциями
start*- restart()
Поддерживаемые варианты перезапуска
- shutdown()
Поддерживаемые варианты завершения
- strategy()
Поддерживаемые стратегии
- sup_flags()
Флаги надзирателя, возвращаемые при инициализации
- supervisor()
Ссылка на надзирателя
- type()
Тип надзирателя.
Обработчики событий
- init(init_arg)
Обработчик, вызываемый для запуска надзирателя и во время горячих обновлений кода.
Функции
- child_spec(module_or_map, overrides)
Создает и переопределяет спецификацию процесса-потомка.
- count_children(supervisor)
Возвращает карту со значениями количества для данного надзирателя.
- delete_child(supervisor, child_id)
Удаляет спецификацию процесса-потомка, идентифицированного по
child_id.- init(children, options)
Получает список спецификаций процессов-потомков для инициализации и набор
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)
Возвращает список с информацией обо всех процессах-потомках данного надзирателя.
Типы
child()Source
@type child() :: pid() | :undefined
Процесс-потомок.
Может быть PID, если процесс-потомок был запущен, или :undefined если он был создан динамическим надзирателем.
child_spec()Source
@type child_spec() :: %{
:id => atom() | term(),
:start => {module(), function_name :: atom(), args :: [term()]},
optional(:restart) => restart(),
optional(:shutdown) => shutdown(),
optional(:type) => type(),
optional(:modules) => [module()] | :dynamic
} Спецификация процесса-потомка для надзирателя.
Определяет, как надзиратель должен запускать, останавливать и перезапускать каждый из своих процессов-потомков.
init_option()Source
@type init_option() ::
{:strategy, strategy()}
| {:max_restarts, non_neg_integer()}
| {:max_seconds, pos_integer()} Параметры, переданные start_link/2 и init/2
name()Source
@type name() :: atom() | {:global, term()} | {:via, module(), term()} Имя надзирателя
on_start()Source
@type on_start() ::
{:ok, pid()}
| :ignore
| {:error, {:already_started, pid()} | {:shutdown, term()} | term()} Возвращаемые значения функций start_link
on_start_child()Source
@type on_start_child() ::
{:ok, child()}
| {:ok, child(), info :: term()}
| {:error, {:already_started, child()} | :already_present | term()} Возвращаемые значения функций start_child
option()Source
@type option() :: {:name, name()} Значения параметров, используемые функциями start*
restart()Source
@type restart() :: :permanent | :transient | :temporary
Поддерживаемые варианты перезапуска
shutdown()Source
@type shutdown() :: pos_integer() | :infinity | :brutal_kill
Поддерживаемые варианты завершения
strategy()Source
@type strategy() :: :one_for_one | :one_for_all | :rest_for_one
Поддерживаемые стратегии
sup_flags()Source
@type sup_flags() :: %{
strategy: strategy(),
intensity: non_neg_integer(),
period: pos_integer()
} Флаги надзирателя, возвращаемые при инициализации
supervisor()Source
@type supervisor() :: pid() | name() | {atom(), node()} Ссылка на надзирателя
type()Source
@type type() :: :worker | :supervisor
Тип надзирателя.
Является ли надзиратель рабочим процессом или другим надзирателем.
Обработчики событий
init(init_arg)Source
@callback init(init_arg :: term()) ::
{:ok,
{sup_flags(),
[child_spec() | (old_erlang_child_spec :: :supervisor.child_spec())]}}
| :ignore Обработчик, вызываемый для запуска надзирателя и во время горячих обновлений кода.
Разработчики обычно вызывают Supervisor.init/2 в конце своего обработчика init, чтобы вернуть соответствующие флаги надзора.
Функции
child_spec(module_or_map, overrides)Source
@spec child_spec(
child_spec() | {module(), arg :: term()} | module(),
keyword()
) :: child_spec() Создаёт и перезаписывает спецификацию дочернего процесса.
Аналогично start_link/2 и init/2, ожидает модуль, {module, arg}, или спецификацию дочернего процесса.
Если передан кортеж из двух элементов в формате {module, arg}, спецификация дочернего процесса извлекается вызовом module.child_spec(arg).
Если передан модуль, спецификация дочернего процесса извлекается вызовом module.child_spec([]).
После извлечения спецификации дочернего процесса поля из 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)Source
@spec 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)Source
@spec delete_child(supervisor(), term()) :: :ok | {:error, error}
when error: :not_found | :running | :restarting Удаляет спецификацию дочернего процесса, идентифицированного по child_id.
Соответствующий дочерний процесс не должен работать; используйте terminate_child/2 для завершения его работы, если он запущен.
При успешном выполнении эта функция возвращает :ok. Эта функция может возвращать ошибку с соответствующим кортежем, если child_id не найден, или если текущий процесс работает или перезапускается.
init(children, options)Source
@spec init(
[
child_spec()
| {module(), term()}
| module()
| (old_erlang_child_spec :: :supervisor.child_spec())
],
[init_option()]
) ::
{:ok,
{sup_flags(),
[child_spec() | (old_erlang_child_spec :: :supervisor.child_spec())]}} Принимает список спецификаций дочерних процессов для инициализации и набор options.
Обычно вызывается в конце обратного вызова init/1 супервайзеров на основе модулей. Смотрите разделы "Стратегии супервайзеров и опции" и "Супервайзеры на основе модулей" в документации модуля для получения дополнительной информации.
Эта функция возвращает кортеж, содержащий флаги супервайзера и спецификации дочерних процессов.
Примеры
def init(_init_arg) do
children = [
{Counter, 0}
]
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)Source
@spec 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)Source
@spec start_child(
supervisor(),
child_spec()
| {module(), term()}
| module()
| (old_erlang_child_spec :: :supervisor.child_spec())
) :: 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)Source
@spec start_link(
[
child_spec()
| {module(), term()}
| module()
| (old_erlang_child_spec :: :supervisor.child_spec())
],
[option() | init_option()]
) ::
{:ok, pid()}
| {:error, {:already_started, pid()} | {:shutdown, term()} | term()} @spec start_link(module(), term()) :: on_start()
Запускает супервайзера с заданными дочерними процессами.
children — это список следующих форм:
спецификация дочернего процесса
модуль, где
module.child_spec([])будет вызван для извлечения его спецификациикортеж из двух элементов в формате
{module, arg}, гдеmodule.child_spec(arg)будет вызван для извлечения его спецификации
Необходима стратегия, предоставляемая через опцию :strategy . См. "Стратегии супервайзеров и опции" для примеров и других опций.
Опции также можно использовать для регистрации имени супервайзера. Поддерживаемые значения описаны в разделе "Регистрация имени" в документации модуля 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 \\ [])Source
@spec 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)Source
@spec stop(supervisor(), reason :: term(), timeout()) :: :ok
Синхронно останавливает заданный супервайзер с заданным reason.
Возвращает :ok если супервайзер завершился с заданным основанием. Если он завершился по другому основанию, вызов завершается.
Эта функция сохраняет семантику OTP относительно обработки ошибок. Если причина отлична от :normal, :shutdown или {:shutdown, _}, сообщается об ошибке.
terminate_child(supervisor, child_id)Source
@spec terminate_child(supervisor(), term()) :: :ok | {:error, :not_found} Прерывает заданного дочернего процесс, идентифицируемого по child_id.
Процесс прерывается, если он существует. Описание дочернего процесса сохраняется, если он не временный.
Процесс дочернего процесса, не являющийся временным, может быть позже перезапущен супервайзером. Дочерний процесс также может быть перезапущен явно, вызвав restart_child/2. Используйте delete_child/2 для удаления описания дочернего процесса.
В случае успеха функция возвращает :ok. Если для данного идентификатора дочернего процесса нет описания, функция возвращает {:error, :not_found}.
which_children(supervisor)Source
@spec which_children(supervisor()) :: [
{term() | :undefined, child() | :restarting, :worker | :supervisor,
[module()] | :dynamic}
] Возвращает список с информацией обо всех дочерних процессах данного супервайзера.
Обратите внимание, что вызов этой функции при наблюдении за большим количеством дочерних процессов в условиях низкой памяти может привести к исключению из-за нехватки памяти.
Функция возвращает список кортежей {id, child, type, modules}, где:
id- как определено в описании дочернего процессаchild- PID соответствующего дочернего процесса,:restartingесли процесс собирается быть перезапущен или:undefinedесли такого процесса нетtype-:workerили:supervisor, как указано в описании дочернего процессаmodules- как указано в описании дочернего процесса
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.14.1/Supervisor.html