Spec-Zone.ru › Elixir 1.9

Начальник поведение

Модуль поведения для реализации начальников.

Начальник — это процесс, который контролирует другие процессы, которые мы называем дочерними процессами. Начальники используются для построения иерархической структуры процессов, называемой деревом управления. Деревья управления обеспечивают отказоустойчивость и инкапсулируют, как запускаются и завершаются наши приложения.

Начальника можно запустить непосредственно со списком детей с помощью 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 - атом, определяющий, как должен быть завершен дочерний процесс (см. раздел "Значения завершения" ниже). Этот ключ необязателен и по умолчанию равен 5000 для типа :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.

Также существует устаревшая стратегия :simple_one_for_one, которая была заменена на DynamicSupervisor. Надзорщик :simple_one_for_one был похож на :one_for_one, но лучше подходит для динамического присоединения потомков. Многие функции в этом модуле вели себя немного по-другому, когда использовалась эта стратегия. Более подробная информация и стратегии миграции представлены в модуле 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()
child_spec()

Спецификация надзорщика

init_option()

Опции, переданные в start_link/2 и init/2

name()

Имя надзорщика

on_start()

Значения возвращаемые функциями start_link

on_start_child()

Значения, возвращаемые функциями start_child

option()

Значения опций, используемые функциями start*

options()

Опции, используемые функциями 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)

Вызываемый обратный вызов для запуска надзорщика и во время горячих обновлений кода.

END_OF_DOCUMENT_MARKER

Типы

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()} | init_option()

Значения параметров, используемые функциями start*

options()

Спецификации

options() :: [option(), ...]

Параметры, используемые функциями start*

strategy()

Спецификации

strategy() :: :one_for_one | :one_for_all | :rest_for_one

Поддерживаемые стратегии

supervisor()

Спецификации

supervisor() :: pid() | name() | {atom(), node()}

Ссылка на супервизор

END_OF_DOCUMENT_MARKER

Функции

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 | :simple_one_for_one | :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, или устаревшая :simple_one_for_one.

  • :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 | :simple_one_for_one | :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() | [term()]
) :: 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()],
  options()
) ::
  {: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(), GenServer.options()) :: 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, _}, регистрируется отчёт об ошибке.

END_OF_DOCUMENT_MARKER

terminate_child(supervisor, child_id)

Характеристики

terminate_child(supervisor(), term()) :: :ok | {:error, error}
when error: :not_found | :simple_one_for_one

Прерывает заданного дочернего процесса, идентифицированного по 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 - как определено в описании дочернего процесса

  • child - 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.9.4/Supervisor.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API