Spec-Zone.ru › Elixir 1.3

Приложение поведение

Модуль для работы с приложениями и определения обратных вызовов приложений.

В Elixir (на самом деле, в Erlang/OTP), приложение — это компонент, реализующий определённую функциональность, который может быть запущен и остановлен как единица и может быть повторно использован в других системах.

Приложения определяются с помощью файла приложения с именем APP.app, где APP — имя приложения, обычно в underscore_case. Файл приложения должен находиться в том же каталоге ebin, что и скомпилированные модули приложения.

В Elixir Mix отвечает за компиляцию исходного кода и создание файла приложения .app. Кроме того, Mix также отвечает за конфигурацию, запуск и остановку вашего приложения и его зависимостей. По этой причине данное руководство будет сосредоточено на оставшихся аспектах вашего приложения: среде приложения и модуле обратного вызова приложения.

Вы можете узнать больше о генерации Mix файлов .app набрав mix help compile.app.

Среда приложения

После запуска приложения OTP предоставляет среду приложения, которую можно использовать для конфигурации приложения.

Предполагая, что вы находитесь внутри проекта Mix, вы можете отредактировать функцию application в файле mix.exs следующим образом:

def application do
  [env: [hello: :world]]
end

В функции приложения мы можем определить значения по умолчанию для среды нашего приложения. Запустив ваше приложение с iex -S mix, вы можете получить доступ к значению по умолчанию:

Application.get_env(:APP_NAME, :hello)
#=> :world

Также возможно добавлять и удалять значения из окружения приложения, включая новые значения, которые не определены в файле среды (хотя этого следует избегать).

Помните, что каждое приложение отвечает за свою среду. Не используйте функции в этом модуле для прямого доступа или изменения среды других приложений (так как это может привести к несогласованным данным в среде приложения).

Обратный вызов модуля приложения

Часто приложение определяет дерево наблюдения, которое должно быть запущено и остановлено при запуске и остановке приложения. Для этого нам нужно определить обратный вызов модуля приложения. Первым шагом является определение обратного вызова модуля в определении приложения в файле mix.exs:

def application do
  [mod: {MyApp, []}]
end

Теперь наше приложение требует модуля MyApp для предоставления обратного вызова приложения. Это можно сделать, вызвав use Application в этом модуле и определив обратный вызов start/2, например:

defmodule MyApp do
  use Application

  def start(_type, _args) do
    MyApp.Supervisor.start_link()
  end
end

start/2 обычно возвращает {:ok, pid} или {:ok, pid, state}, где pid идентифицирует дерево наблюдения, а state — состояние приложения. args — второй элемент кортежа, переданного опции :mod.

Аргумент type, переданный start/2, обычно является :normal, за исключением распределённой среды, где настроены передача и отказ приложения. Этот конкретный аспект приложений более подробно описан в документации OTP:

  • :application модуль
  • Приложения — принципы проектирования OTP

Разработчик также может реализовать обратный вызов stop/1 (автоматически определённый use Application), который выполняет очистку приложения. Он получает состояние приложения и может вернуть любое значение. Обратите внимание, что завершение работы надзорщика автоматически обрабатывается виртуальной машиной.

Резюме

Типы

app()
key()
start_type()
state()
value()

Функции

app_dir(app)

Возвращает каталог для приложения

app_dir(app, path)

Возвращает указанный путь внутри app_dir/1

delete_env(app, key, opts \\ [])

Удаляет key из указанной среды app.

ensure_all_started(app, type \\ :temporary)

Обеспечивает запуск указанного app и его приложений.

ensure_started(app, type \\ :temporary)

Обеспечивает запуск указанного app.

fetch_env(app, key)

Возвращает значение для key в среде app в кортеже

fetch_env!(app, key)

Возвращает значение для key в среде app.

format_error(reason)

Форматирует причину ошибки, возвращённую start/2, ensure_started/2, stop/1, load/1 и unload/1, возвращает строку

get_all_env(app)

Возвращает все пары ключ-значение для app.

get_application(module)

Получает приложение для данного модуля.

get_env(app, key, default \\ nil)

Возвращает значение для key в среде app.

load(app)

Загружает указанное app.

loaded_applications()

Возвращает список с информацией о загруженных приложениях.

put_env(app, key, value, opts \\ [])

Добавляет value в key для указанного app.

spec(app)

Возвращает спецификацию для app.

spec(app, key)

Возвращает значение для key в спецификации app.

start(app, type \\ :temporary)

Запускает указанное app.

started_applications(timeout \\ 5000)

Возвращает список с информацией о работающих приложениях.

stop(app)

Останавливает указанное app.

unload(app)

Выгружает указанное app.

Обратные вызовы

start(start_type, start_args)

Вызывается при запуске приложения.

stop(state)

Вызывается при остановке приложения.

Типы

app()

app() :: atom

key()

key() :: atom

start_type()

start_type() :: :permanent | :transient | :temporary

state()

state() :: term

value()

value() :: term

Функции

app_dir(app)

app_dir(app) :: String.t

Возвращает каталог для приложения.

Эта информация возвращается на основе пути кода. Вот пример:

File.mkdir_p!("foo/ebin")
Code.prepend_path("foo/ebin")
Application.app_dir(:foo)
#=> "foo"

Даже если каталог пустой и нет файла .app, он рассматривается как каталог приложения на основе имени «foo/ebin». Имя может содержать дефис -, который считается версией приложения, и он удаляется для целей поиска:

File.mkdir_p!("bar-123/ebin")
Code.prepend_path("bar-123/ebin")
Application.app_dir(:bar)
#=> "bar-123"

Для получения дополнительной информации о путях кода обратитесь к модулю Code в Elixir и модулю :code в Erlang.

app_dir(app, path)

app_dir(app, String.t | [String.t]) :: String.t

Возвращает указанный путь внутри app_dir/1.

delete_env(app, key, opts \\ [])

delete_env(app, key, [timeout: timeout, persistent: boolean]) :: :ok

Удаляет key из указанной среды app.

См. put_env/4 для описания опций.

ensure_all_started(app, type \\ :temporary)

ensure_all_started(app, start_type) ::
  {:ok, [app]} |
  {:error, {app, term}}

Обеспечивает запуск указанного app и его приложений.

Аналогично start/2, но также запускает приложения, перечисленные в :applications в файле .app в случае, если они ранее не запускались.

ensure_started(app, type \\ :temporary)

ensure_started(app, start_type) :: :ok | {:error, term}

Обеспечивает запуск заданного app.

То же самое, что и start/2, но возвращает :ok, если приложение уже запущено. Это полезно в скриптах и при настройке тестов, где тестовые приложения необходимо явно запускать:

:ok = Application.ensure_started(:my_test_dep)

fetch_env(app, key)

fetch_env(app, key) :: {:ok, value} | :error

Возвращает значение для key в среде app в виде кортежа.

Если параметр конфигурации не существует, функция возвращает :error.

fetch_env!(app, key)

fetch_env!(app, key) :: value | no_return

Возвращает значение для key в среде app.

Если параметр конфигурации не существует, генерирует исключение ArgumentError.

format_error(reason)

format_error(any) :: String.t

Форматирует причину ошибки, возвращаемую функциями start/2, ensure_started/2, stop/1, load/1 и unload/1, возвращает строку.

get_all_env(app)

get_all_env(app) :: [{key, value}]

Возвращает все пары ключ-значение для app.

get_application(module)

get_application(atom) :: atom | nil

Получает приложение для данного модуля.

Приложение находится путем анализа спецификаций всех загруженных приложений. Возвращает nil, если модуль не указан в спецификации ни одного приложения.

get_env(app, key, default \\ nil)

get_env(app, key, value) :: value

Возвращает значение для key в среде app.

Если параметр конфигурации не существует, функция возвращает значение default.

load(app)

load(app) :: :ok | {:error, term}

Загружает заданное app.

Для загрузки файл .app должен находиться в пути загрузки. Все :included_applications также будут загружены.

Загрузка приложения не запускает его и не загружает его модули, но загружает его среду.

loaded_applications()

loaded_applications() :: [tuple]

Возвращает список с информацией о загруженных приложениях.

put_env(app, key, value, opts \\ [])

put_env(app, key, value, [timeout: timeout, persistent: boolean]) :: :ok

Устанавливает value в среде key для заданного app.

Параметры

  • :timeout - таймаут изменения (по умолчанию 5000 мс)
  • :persistent - сохраняет заданное значение при загрузке и перезагрузке приложения

Если put_env/4 вызывается до загрузки приложения, значения среды приложения, указанные в файле .app, переопределят ранее установленные.

Параметр «persistent» можно установить в true, когда необходимо гарантировать, что параметры, установленные этой функцией, не будут переопределены параметрами, определёнными в файле ресурса приложения при загрузке. Это означает, что постоянные значения сохранятся после загрузки приложения и при его перезагрузке.

spec(app)

spec(app) :: [{key, value}] | nil

Возвращает спецификацию для app.

Возвращаются следующие ключи:

  • :description
  • :id
  • :vsn
  • :modules
  • :maxP
  • :maxT
  • :registered
  • :included_applications
  • :applications
  • :mod
  • :start_phases

Обратите внимание, что среда не возвращается, так как к ней можно получить доступ через fetch_env/2. Возвращает nil, если приложение не загружено.

spec(app, key)

spec(app, key) :: value | nil

Возвращает значение для key в спецификации app.

См. spec/1 для поддерживаемых ключей. Если заданный параметр спецификации не существует, эта функция генерирует исключение. Возвращает nil, если приложение не загружено.

start(app, type \\ :temporary)

start(app, start_type) :: :ok | {:error, term}

Запускает заданное app.

Если app не загружено, приложение сначала будет загружено с помощью load/1. Любое включенное приложение, определённое в ключе :included_applications файла .app, также будет загружено, но не запущено.

Кроме того, все приложения, перечисленные в ключе :applications, должны быть явно запущены перед запуском этого приложения. В противном случае, возвращается {:error, {:not_started, app}}, где app — имя отсутствующего приложения.

Если вы хотите автоматически загрузить и запустить все зависимости app, см. ensure_all_started/2.

Аргумент type указывает тип приложения:

  • :permanent — если app завершается, все другие приложения и весь узел также завершаются.

  • :transient — если app завершается с причиной :normal, она сообщается, но другие приложения не завершаются. Если транзиентное приложение завершается аномально, все другие приложения и весь узел также завершаются.

  • :temporary — если app завершается, она сообщается, но другие приложения не завершаются (по умолчанию).

Обратите внимание, что всегда можно явно остановить приложение, вызвав stop/1. Независимо от типа приложения, другие приложения не будут затронуты.

Также обратите внимание, что тип :transient практически бесполезен, так как при завершении дерева наблюдения причина устанавливается в :shutdown, а не в :normal.

started_applications(timeout \\ 5000)

started_applications(timeout) :: [tuple]

Возвращает список с информацией о приложениях, которые в данный момент работают.

stop(app)

stop(app) :: :ok | {:error, term}

Останавливает заданное app.

После остановки приложение всё ещё загружено.

unload(app)

unload(app) :: :ok | {:error, term}

Выгружает заданное app.

Также будут выгружены все :included_applications. Обратите внимание, что функция не очищает модули приложения.

Обратные вызовы

start(start_type, start_args)

start(start_type, start_args :: term) ::
  {:ok, pid} |
  {:ok, pid, state} |
  {:error, reason :: term}

Вызывается при запуске приложения.

Эта функция вызывается при запуске приложения с помощью Application.start/2 (и функций, которые на ней основаны, таких как Application.ensure_started/2). Эта функция должна запускать основной процесс приложения (который должен быть верхним супервайзером дерева наблюдения приложения, если приложение следует принципам OTP в отношении супервайзинга).

start_type определяет, как запускается приложение:

  • :normal — используется, если запуск — обычный запуск или если приложение распределено и запускается на текущем узле из-за переключения с другого режима, а ключ спецификации приложения :start_phases равен :undefined.
  • {:takeover, node} — используется, если приложение распределено и запускается на текущем узле из-за переключения на узле node.
  • {:failover, node} — используется, если приложение распределено и запускается на текущем узле из-за переключения на узле node, а ключ спецификации приложения :start_phases не равен :undefined.

start_args — это аргументы, передаваемые приложению в ключе спецификации :mod (например, mod: {MyApp, [:my_args]}).

Эта функция должна возвращать {:ok, pid} или {:ok, pid, state} в случае успешного запуска. pid должен быть идентификатором (PID) верхнего супервайзера. state может быть произвольным значением и по умолчанию будет []; если приложение позже останавливается, state передаётся обратно в обратный вызов stop/1 (см. документацию для обратного вызова stop/2 для получения дополнительной информации).

use Application не предоставляет реализации по умолчанию для обратного вызова start/2.

stop(state)

stop(state) :: term

Вызывается при остановке приложения.

Эта функция вызывается, когда приложение остановлено, т.е. когда его дерево наблюдения остановлено. Она должна делать обратное тому, что делал обратный вызов start/2, и должна выполнять необходимые операции по очистке. Возвращаемое значение этого обратного вызова игнорируется.

state — это возвращаемое значение обратного вызова start/2 или возвращаемое значение функции prep_stop/1, если модуль приложения определяет такую функцию.

use Application определяет реализацию по умолчанию этой функции, которая ничего не делает и просто возвращает :ok.

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.3.4/Application.html

Spec-Zone.ru

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