Task.Supervisor
Наблюдатель задач.
Этот модуль определяет наблюдателя, который может использоваться для динамического наблюдения за задачами.
Наблюдатель задач запускается без дочерних задач, часто под управлением наблюдателя и с именем:
children = [
{Task.Supervisor, name: MyApp.TaskSupervisor}
]
Supervisor.start_link(children, strategy: :one_for_one)
Параметры, указанные в спецификации дочерней задачи, документированы в start_link/1.
См. модуль Task для получения дополнительных примеров.
Регистрация имени
Наблюдатель связан с правилами регистрации имен так же, как и GenServer. Подробнее об этом можно прочитать в документации GenServer.
Краткое описание
Типы
- option()
Значения параметров, используемые
start_link
Функции
- async(supervisor, fun, options \\ [])
Запускает задачу, на которой можно ожидать завершения.
- async(supervisor, module, fun, args, options \\ [])
Запускает задачу, на которой можно ожидать завершения.
- async_nolink(supervisor, fun, options \\ [])
Запускает задачу, на которой можно ожидать завершения.
- async_nolink(supervisor, module, fun, args, options \\ [])
Запускает задачу, на которой можно ожидать завершения.
- async_stream(supervisor, enumerable, fun, options \\ [])
Возвращает поток, который выполняет заданную функцию
funодновременно на каждом элементе вenumerable.- async_stream(supervisor, enumerable, module, function, args, options \\ [])
Возвращает поток, где заданная функция (
moduleиfunction) применяется одновременно к каждому элементу вenumerable.- async_stream_nolink(supervisor, enumerable, fun, options \\ [])
Возвращает поток, который выполняет данную
functionодновременно на каждом элементе вenumerable.- async_stream_nolink(supervisor, enumerable, module, function, args, options \\ [])
Возвращает поток, где заданная функция (
moduleиfunction) применяется одновременно к каждому элементу вenumerable.- children(supervisor)
Возвращает все идентификаторы дочерних процессов.
- start_child(supervisor, fun, options \\ [])
Запускает задачу как дочернюю задачу данного
supervisor.- start_child(supervisor, module, fun, args, options \\ [])
Запускает задачу как дочернюю задачу данного
supervisor.- start_link(options \\ [])
Запускает нового наблюдателя.
- terminate_child(supervisor, pid)
Завершает дочернюю задачу с данным
pid.
Типы
option()
Specs
option() ::
DynamicSupervisor.option()
| {:restart, :supervisor.restart()}
| {:shutdown, :supervisor.shutdown()} Значения параметров, используемые start_link
Функции
async(supervisor, fun, options \\ [])
Характеристики
async(Supervisor.supervisor(), (() -> any()), Keyword.t()) :: Task.t()
Запускает задачу, на которой можно ожидать.
Аргумент supervisor должен быть ссылкой, как определено в Supervisor. Задача по-прежнему будет связана с вызывающим процессом, см. Task.async/3 для получения дополнительной информации и async_nolink/2 для варианта без связи.
Вызывает ошибку, если supervisor достигла максимального количества дочерних задач.
Параметры
-
:shutdown-:brutal_killесли задачи необходимо убить при завершении работы, или целое число, указывающее значение таймаута, по умолчанию 5000 миллисекунд.
async(supervisor, module, fun, args, options \\ [])
Характеристики
async(Supervisor.supervisor(), module(), atom(), [term()], Keyword.t()) :: Task.t()
Запускает задачу, на которой можно ожидать.
Аргумент supervisor должен быть ссылкой, как определено в Supervisor. Задача по-прежнему будет связана с вызывающим процессом, см. Task.async/3 для получения дополнительной информации и async_nolink/2 для варианта без связи.
Вызывает ошибку, если supervisor достигла максимального количества дочерних задач.
Параметры
-
:shutdown-:brutal_killесли задачи необходимо убить при завершении работы, или целое число, указывающее значение таймаута, по умолчанию 5000 миллисекунд.
async_nolink(supervisor, fun, options \\ [])
Характеристики
async_nolink(Supervisor.supervisor(), (() -> any()), Keyword.t()) :: Task.t()
Запускает задачу, на которой можно ожидать.
Аргумент supervisor должен быть ссылкой, как определено в Supervisor. Задача не будет связана с вызывающим процессом, см. Task.async/3 для получения дополнительной информации.
Вызывает ошибку, если supervisor достигла максимального количества дочерних задач.
Параметры
-
:shutdown-:brutal_killесли задачи необходимо убить при завершении работы, или целое число, указывающее значение таймаута, по умолчанию 5000 миллисекунд.
Совместимость с поведением OTP
Если вы создаёте задачу, используя async_nolink внутри поведения OTP, например, GenServer, вы должны обрабатывать сообщение, приходящее от задачи внутри вашего обратного вызова GenServer.handle_info/2.
Ответ, отправленный задачей, будет в формате {ref, result}, где ref — ссылка мониторинга, хранящаяся в структуре задачи, а result — возвращаемое значение функции задачи.
Помните, что независимо от того, как завершается задача, созданная с помощью async_nolink, вызывающий процесс всегда получит сообщение :DOWN с тем же значением ref, которое хранится в структуре задачи. Если задача завершается нормально, причина в сообщении :DOWN будет :normal.
Примеры
Обычно вы используете async_nolink/3, когда есть обоснованное ожидание, что задача может завершиться ошибкой, и вы не хотите, чтобы она привела к завершению вызывающего процесса. Посмотрим пример, где GenServer предназначен для выполнения одной задачи и отслеживания её состояния:
defmodule MyApp.Server do
use GenServer
# ...
def start_task do
GenServer.call(__MODULE__, :start_task)
end
# In this case the task is already running, so we just return :ok.
def handle_call(:start_task, _from, %{ref: ref} = state) when is_reference(ref) do
{:reply, :ok, state}
end
# The task is not running yet, so let's start it.
def handle_call(:start_task, _from, %{ref: nil} = state) do
task =
Task.Supervisor.async_nolink(MyApp.TaskSupervisor, fn ->
...
end)
# We return :ok and the server will continue running
{:reply, :ok, %{state | ref: task.ref}}
end
# The task completed successfully
def handle_info({ref, answer}, %{ref: ref} = state) do
# We don't care about the DOWN message now, so let's demonitor and flush it
Process.demonitor(ref, [:flush])
# Do something with the result and then return
{:noreply, %{state | ref: nil}}
end
# The task failed
def handle_info({:DOWN, ref, :process, _pid, _reason}, %{ref: ref} = state) do
# Log and possibly restart the task...
{:noreply, %{state | ref: nil}}
end
end async_nolink(supervisor, module, fun, args, options \\ [])
Характеристики
async_nolink(Supervisor.supervisor(), module(), atom(), [term()], Keyword.t()) :: Task.t()
Запускает задачу, на которой можно ожидать.
Аргумент supervisor должен быть ссылкой, как определено в Supervisor. Задача не будет связана с вызывающим процессом, см. Task.async/3 для получения дополнительной информации.
Вызывает ошибку, если supervisor достигла максимального количества дочерних задач.
Обратите внимание, что для этой функции требуется, чтобы у надзирателя задач был параметр :temporary в качестве параметра :restart (значение по умолчанию), так как async_nolink/4 сохраняет прямую ссылку на задачу, которая теряется, если задача перезапускается.
async_stream(supervisor, enumerable, fun, options \\ [])
Характеристики
async_stream( Supervisor.supervisor(), Enumerable.t(), (term() -> term()), keyword() ) :: Enumerable.t()
Возвращает поток, который выполняет заданную функцию fun асинхронно для каждого элемента в enumerable.
Каждый элемент в enumerable передаётся в качестве аргумента в заданную функцию fun и обрабатывается собственной задачей. Задачи будут созданы под заданным supervisor и связаны с текущим процессом, аналогично async/2.
См. async_stream/6 для обсуждения, параметров и примеров.
async_stream(supervisor, enumerable, module, function, args, options \\ [])
Характеристики
async_stream( Supervisor.supervisor(), Enumerable.t(), module(), atom(), [term()], keyword() ) :: Enumerable.t()
Возвращает поток, где заданная функция (module и function) применяется асинхронно для каждого элемента в enumerable.
Каждый элемент будет добавлен перед заданным args и обработан собственной задачей. Задачи будут созданы под заданным supervisor и связаны с текущим процессом, аналогично async/4.
При потоковой передаче каждая задача будет генерировать {:ok, value} при успешном завершении или {:exit, reason} если вызывающий процесс обрабатывает завершения. Порядок результатов зависит от значения параметра :ordered.
Уровень параллельности и время выполнения задач можно контролировать с помощью параметров (см. раздел "Параметры" ниже).
Если вы обрабатываете завершения внутри асинхронного потока, рассмотрите использование async_stream_nolink/6 для запуска задач, не связанных с вызывающим процессом.
Параметры
:max_concurrency- устанавливает максимальное количество задач, выполняемых одновременно. По умолчаниюSystem.schedulers_online/0.:ordered- возвращать ли результаты в том же порядке, что и входной поток. Этот параметр полезен для больших потоков, чтобы не буферизовать результаты перед их доставкой. Это также полезно, когда вы используете задачи для побочных эффектов. По умолчаниюtrue.:timeout- максимальное время ожидания (в миллисекундах) без получения ответа от задачи (по всем запущенным задачам). По умолчанию5000.-
:on_timeout- что делать, когда задача истекает. Возможные значения:-
:exit(по умолчанию) - процесс, который запустил задачи, завершается. -
:kill_task- задача, которая истекла, убивается. Итоговое значение для этой задачи{:exit, :timeout}.
-
:shutdown-:brutal_killесли задачи необходимо убить при завершении работы, или целое число, указывающее значение таймаута. По умолчанию5000миллисекунд.
Примеры
Давайте создадим поток и затем перечислим его:
stream = Task.Supervisor.async_stream(MySupervisor, collection, Mod, :expensive_fun, []) Enum.to_list(stream)
async_stream_nolink(supervisor, enumerable, fun, options \\ [])
Характеристики
async_stream_nolink( Supervisor.supervisor(), Enumerable.t(), (term() -> term()), keyword() ) :: Enumerable.t()
Возвращает поток, который выполняет заданную function асинхронно для каждого элемента в enumerable.
Каждый элемент в enumerable передаётся в качестве аргумента в заданную функцию fun и обрабатывается собственной задачей. Задачи будут созданы под заданным supervisor и не будут связаны с текущим процессом, аналогично async_nolink/2.
См. async_stream/6 для обсуждения и примеров.
async_stream_nolink(supervisor, enumerable, module, function, args, options \\ [])
Характеристики
async_stream_nolink( Supervisor.supervisor(), Enumerable.t(), module(), atom(), [term()], keyword() ) :: Enumerable.t()
Возвращает поток, где заданная функция (module и function) применяется асинхронно для каждого элемента в enumerable.
Каждый элемент в enumerable будет добавлен перед заданным args и обработан собственной задачей. Задачи будут созданы под заданным supervisor и не будут связаны с текущим процессом, аналогично async_nolink/4.
См. async_stream/6 для обсуждения, параметров и примеров.
children(supervisor)
Характеристики
children(Supervisor.supervisor()) :: [pid()]
Возвращает все идентификаторы дочерних процессов.
start_child(supervisor, fun, options \\ [])
Характеристики
start_child(Supervisor.supervisor(), (() -> any()), keyword()) :: DynamicSupervisor.on_start_child()
Запускает задачу как дочернюю задачу заданного supervisor.
Обратите внимание, что запущенный процесс не связан с вызывающим, а только с надзирателем. Эта команда полезна в случае, если задаче необходимо выполнить побочные эффекты (например, ввод-вывод) и ей не нужно сообщать обратно вызывающему.
Параметры
:restart— стратегия перезапуска, может быть:temporary(по умолчанию),:transientили:permanent.:temporaryозначает, что задача никогда не будет перезапущена,:transientозначает, что она перезапускается, если выход не:normal,:shutdownили{:shutdown, reason}. Стратегия перезапуска:permanentозначает, что она всегда перезапускается. По умолчанию:temporary.:shutdown—:brutal_killесли задачи должны быть убиты при выключении, или целое число, указывающее значение таймаута, по умолчанию 5000 миллисекунд.
start_child(supervisor, module, fun, args, options \\ [])
Характеристики
start_child(Supervisor.supervisor(), module(), atom(), [term()], keyword()) :: DynamicSupervisor.on_start_child()
Запускает задачу как дочернюю задачу заданного supervisor.
Аналогично start_child/2, за исключением того, что задача задается указанным module, fun и args.
start_link(options \\ [])
Характеристики
start_link([option()]) :: Supervisor.on_start()
Запускает нового надзирателя.
Примеры
Надзиратель задач обычно запускается в иерархии надзора с помощью кортежа:
{Task.Supervisor, name: MyApp.TaskSupervisor}
Вы также можете запустить его, вызвав start_link/1 напрямую:
Task.Supervisor.start_link(name: MyApp.TaskSupervisor)
Но это рекомендуется только для скриптов и следует избегать в рабочем коде. Как правило, процессы всегда должны запускаться внутри иерархий надзора.
Параметры
:name— используется для регистрации имени надзирателя, допустимые значения описаны в разделеName Registrationв документации модуляGenServer;:max_restarts,:max_secondsи:max_children— как указано вDynamicSupervisor;
Эта функция также может принимать :restart и :shutdown в качестве параметров, но эти два параметра устарели, и теперь предпочтительнее передавать их напрямую в start_child и async.
terminate_child(supervisor, pid)
Характеристики
terminate_child(Supervisor.supervisor(), pid()) :: :ok | {:error, :not_found} Завершает дочерний процесс с заданным pid.
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.10.4/Task.Supervisor.html