Spec-Zone.ru › Elixir 1.14

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

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

Приложения — это стандартный способ упаковки программного обеспечения в Erlang/OTP. По сути, они похожи на концепцию «библиотеки», распространённую в других языках программирования, но с некоторыми дополнительными характеристиками.

Приложение — это компонент, реализующий определённую функциональность со стандартной структурой каталогов, конфигурацией и жизненным циклом. Приложения загружаются, запускаются и останавливаются. Каждое приложение также имеет собственную среду, которая предоставляет унифицированный API для конфигурации каждого приложения.

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

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

Каждое приложение имеет свою собственную среду. Среда — это список ключевых слов, сопоставляющих атомы с терминами. Обратите внимание, что эта среда не связана со средой операционной системы.

По умолчанию среда приложения — это пустой список. В файле mix.exs проекта Mix вы можете установить ключ :env в application/0.

def application do
  [env: [db_host: "localhost"]]
end

Теперь в вашем приложении вы можете прочитать эту среду, используя функции, такие как fetch_env!/2 и аналогичные:

defmodule MyApp.DBClient do
  def start_link() do
    SomeLib.DBClient.start_link(host: db_host())
  end

  defp db_host do
    Application.fetch_env!(:my_app, :db_host)
  end
end

В проектах Mix среда приложения и его зависимостей может быть переопределена через файлы config/config.exs и config/runtime.exs. Первый загружается на этапе компиляции, до компиляции вашего кода, а второй — во время выполнения, непосредственно перед запуском вашего приложения. Например, кто-то, использующий ваше приложение, может переопределить переменную среды :db_host следующим образом:

import Config
config :my_app, :db_host, "db.local"

Дополнительную информацию см. в разделе «Конфигурация» в модуле Mix. Вы также можете динамически изменять среду приложения, используя функции, такие как put_env/3 и delete_env/2.

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

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

Среда времени компиляции

В предыдущем примере мы читали среду приложения во время выполнения:

defmodule MyApp.DBClient do
  def start_link() do
    SomeLib.DBClient.start_link(host: db_host())
  end

  defp db_host do
    Application.fetch_env!(:my_app, :db_host)
  end
end

Другими словами, ключ среды :db_host для приложения :my_app будет прочитан только тогда, когда приложение MyApp.DBClient фактически запустится. Хотя чтение среды приложения во время выполнения предпочтительнее, в некоторых редких случаях вы можете захотеть использовать среду приложения для конфигурации компиляции определённого проекта. Однако если вы попытаетесь получить доступ к Application.fetch_env!/2 вне функции:

defmodule MyApp.DBClient do
  @db_host Application.fetch_env!(:my_app, :db_host)

  def start_link() do
    SomeLib.DBClient.start_link(host: @db_host)
  end
end

Вы можете увидеть предупреждения и ошибки:

warning: Application.fetch_env!/2 is discouraged in the module body,
use Application.compile_env/3 instead
  iex:3: MyApp.DBClient

** (ArgumentError) could not fetch application environment :db_host
for application :my_app because the application was not loaded nor
configured

Это происходит потому, что при определении модулей среда приложения ещё недоступна. К счастью, предупреждение показывает, как решить эту проблему, используя Application.compile_env/3 вместо этого:

defmodule MyApp.DBClient do
  @db_host Application.compile_env(:my_app, :db_host, "db.local")

  def start_link() do
    SomeLib.DBClient.start_link(host: @db_host)
  end
end

Разница в том, что compile_env ожидает, что значение по умолчанию будет передано в качестве аргумента, а не используя функцию def application вашего модуля mix.exs. Кроме того, используя compile_env/3, инструменты, такие как Mix, будут сохранять значения, используемые во время компиляции, и сравнивать значения компиляции со значениями во время выполнения при запуске вашей системы, вызывая ошибку в случае их различия.

В любом случае, следует избегать сред времени компиляции. В случае возможности чтение среды приложения во время выполнения должно быть первоочередным.

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

Приложения могут загружаться, запускаться и останавливаться. Обычно инструменты сборки, такие как Mix, позаботятся о запуске приложения и всех его зависимостей, но вы также можете сделать это вручную, вызвав:

{:ok, _} = Application.ensure_all_started(:some_app)

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

Первый шаг — добавить ключ :mod к определению application/0 в вашем файле mix.exs. Он ожидает кортеж, содержащий модуль обратного вызова приложения и аргумент запуска (обычно пустой список):

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

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

defmodule MyApp do
  use Application

  def start(_type, _args) do
    children = []
    Supervisor.start_link(children, strategy: :one_for_one)
  end
end

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

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

При завершении приложения вызывается обратный вызов stop/1 после остановки дерева надзора системой выполнения. Этот обратный вызов позволяет приложению выполнить окончательную очистку. Аргумент — состояние, возвращённое start/2, если оно было, или [] в противном случае. Возвращаемое значение stop/1 игнорируется.

Используя Application, модули получают реализацию по умолчанию для stop/1, которая игнорирует свой аргумент и возвращает :ok, но её можно переопределить.

Модули обратных вызовов приложений также могут реализовать необязательный обратный вызов prep_stop/1. Если он присутствует, prep_stop/1 вызывается перед завершением дерева надзора. Его аргументом является состояние, возвращённое start/2, если оно было, или [] в противном случае, а его возвращаемое значение передаётся в stop/1.

Файл ресурсов приложения

В предыдущих разделах мы настроили приложение в разделе application/0 файла mix.exs. В конечном итоге Mix использует эту конфигурацию для создания файла файла ресурсов приложения, который называется APP_NAME.app. Например, файл ресурсов приложения приложения OTP ex_unit называется ex_unit.app.

Дополнительную информацию о генерации файлов ресурсов приложений вы можете найти в документации Mix.Tasks.Compile.App, доступной также посредством выполнения mix help compile.app.

Жизненный цикл приложения

Загрузка приложений

Приложения загружаются, что означает, что система выполнения находит и обрабатывает их файлы ресурсов:

Application.load(:ex_unit)
#=> :ok

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

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

На практике вы редко загружаете приложения вручную, так как это часть процесса запуска, описанного ниже.

Запуск приложений

Приложения также запускаются:

Application.start(:ex_unit)
#=> :ok

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

При запуске приложения функция Application.load/1 автоматически вызывается, если она ещё не была выполнена. Затем она проверяет, являются ли зависимости, перечисленные в ключе applications файла ресурсов, уже запущенными. Наличие хотя бы одной не запущенной зависимости — это условие ошибки. Функции, такие как ensure_all_started/1 , позаботятся о запуске приложения и всех его зависимостей.

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

Остановка приложений

Запущенные приложения, наконец, останавливаются:

Application.stop(:ex_unit)
#=> :ok

Остановка приложения без модуля обратного вызова определена, но, за исключением некоторого системного отслеживания, она фактически является пустой операцией.

Остановка приложения с модулем обратного вызова имеет три шага:

  1. Если присутствует, вызывается необязательный обратный вызов prep_stop/1.
  2. Завершается верхний диспетчер.
  3. Вызывается обязательный обратный вызов stop/1.

Передаваемые аргументы обратным вызовам связаны с состоянием, которое необязательно возвращается start/2, и подробно описаны в разделе о модуле обратных вызовов выше.

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

Чистую остановку действующей системы можно выполнить, вызвав System.stop/1. Она остановит каждое приложение в обратном порядке их запуска.

По умолчанию, SIGTERM из операционной системы автоматически переводится в System.stop/0. Вы также можете получить больший контроль над сигналами операционной системы с помощью функции :os.set_signal/2.

Инструменты

Инструмент сборки Mix автоматизирует большинство задач управления приложениями. Например, mix test автоматически запускает зависимости вашего приложения и само приложение перед выполнением тестов. mix run --no-halt запускает текущий проект и может использоваться для запуска долгоживущей системы. См. mix help run.

Разработчики также могут использовать mix release для создания релизов. Релизы способны упаковать весь исходный код, а также виртуальную машину Erlang в один каталог. Релизы также предоставляют явный контроль над тем, как и в каком порядке запускается каждое приложение. Они также обеспечивают более удобный механизм запуска и остановки систем, отладки, ведения журналов, а также мониторинга системы.

Наконец, Elixir предоставляет инструменты, такие как escripts и архивы, которые являются различными механизмами для упаковки приложения. Они обычно используются, когда инструменты должны быть общими для разработчиков, а не в качестве вариантов развертывания. См. mix help archive.build и mix help escript.build для получения более подробной информации.

Дополнительная информация

Для получения дополнительной информации об приложениях, пожалуйста, обратитесь к документации модуля :application Erlang и разделу Приложения в руководстве по принципам проектирования OTP .

Резюме

Типы

app()
application_key()
key()
restart_type()
start_type()
state()
value()

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

config_change(changed, new, removed)

Обратный вызов, вызываемый после обновления кода, если среда приложения изменилась.

prep_stop(state)

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

start(start_type, start_args)

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

start_phase(phase, start_type, phase_args)

Запускает приложение в синхронных фазах.

stop(state)

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

Функции

app_dir(app)

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

app_dir(app, path)

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

compile_env(app, key_or_path, default \\ nil)

Считывает среду приложения во время компиляции.

compile_env(env, app, key_or_path, default)

Считывает среду приложения во время компиляции из макроса.

compile_env!(app, key_or_path)

Считывает среду приложения во время компиляции или генерирует исключение.

compile_env!(env, app, key_or_path)

Считывает среду приложения во время компиляции из макроса или генерирует исключение.

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

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

ensure_all_started(app, type \\ :temporary)

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

ensure_loaded(app)

Обеспечивает загрузку данного 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_all_env(config, opts \\ [])

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

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.

END_OF_DOCUMENT_MARKER

Типы

app()Source

@type app() :: atom()

application_key()Source

@type application_key() ::
  :start_phases
  | :mod
  | :applications
  | :optional_applications
  | :included_applications
  | :registered
  | :maxT
  | :maxP
  | :modules
  | :vsn
  | :id
  | :description

key()Source

@type key() :: atom()

restart_type()Source

@type restart_type() :: :permanent | :transient | :temporary

start_type()Source

@type start_type() :: :normal | {:takeover, node()} | {:failover, node()}

state()Source

@type state() :: term()

value()Source

@type value() :: term()

Обработчики

config_change(changed, new, removed)Source

@callback config_change(changed, new, removed) :: :ok
when changed: keyword(), new: keyword(), removed: [atom()]

Обработчик, вызываемый после обновления кода, если среда приложения изменилась.

changed — это список ключевых слов с ключами и их изменёнными значениями в среде приложения. new — это список ключевых слов со всеми новыми ключами и их значениями. removed — это список всех удалённых ключей.

prep_stop(state)Source

@callback prep_stop(state()) :: state()

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

Эта функция вызывается перед завершением верхнего уровня супервизора. Она получает состояние, возвращённое start/2, если оно было, или [] в противном случае. Возвращаемое значение впоследствии передаётся в stop/1.

start(start_type, start_args)Source

@callback 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/1 для получения дополнительной информации).

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

start_phase(phase, start_type, phase_args)Source

@callback start_phase(phase :: term(), start_type(), phase_args :: term()) ::
  :ok | {:error, reason :: term()}

Запускает приложение в синхронных фазах.

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

stop(state)Source

@callback stop(state()) :: term()

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

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

state — это состояние, возвращённое start/2, если оно было, или [] в противном случае. Если опциональный обратный вызов prep_stop/1 присутствует, state — это его возвращаемое значение.

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

END_OF_DOCUMENT_MARKER

Функции

app_dir(app)Source

@spec app_dir(app()) :: String.t()

Получает директорию для приложения app.

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

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)Source

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

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

Если path является строкой, то она будет использоваться как путь внутри app_dir/1. Если path является списком строк, он будет объединен (см. Path.join/1), и результат будет использован как путь внутри app_dir/1.

Примеры

File.mkdir_p!("foo/ebin")
Code.prepend_path("foo/ebin")

Application.app_dir(:foo, "my_path")
#=> "foo/my_path"

Application.app_dir(:foo, ["my", "nested", "path"])
#=> "foo/my/nested/path"

compile_env(app, key_or_path, default \\ nil)Source

@spec compile_env(app(), key() | list(), value()) :: value()

Считывает среду приложения во время компиляции.

Аналогично get_env/3, за исключением того, что он должен использоваться для чтения значений во время компиляции. Это позволяет Elixir отслеживать изменения значений конфигурации между временем компиляции и временем выполнения.

Первый аргумент - это имя приложения. Второй аргумент key_or_path - это либо атомный ключ, либо путь для обхода в поисках конфигурации, начиная с атомного ключа.

Например, представьте следующую конфигурацию:

config :my_app, :key, [foo: [bar: :baz]]

Мы можем получить к нему доступ во время компиляции как:

Application.compile_env(:my_app, :key)
#=> [foo: [bar: :baz]]

Application.compile_env(:my_app, [:key, :foo])
#=> [bar: :baz]

Application.compile_env(:my_app, [:key, :foo, :bar])
#=> :baz

Значение по умолчанию также может быть задано в качестве третьего аргумента. Если какой-либо из ключей на пути отсутствует, используется значение по умолчанию:

Application.compile_env(:my_app, [:unknown, :foo, :bar], :default)
#=> :default

Application.compile_env(:my_app, [:key, :unknown, :bar], :default)
#=> :default

Application.compile_env(:my_app, [:key, :foo, :unknown], :default)
#=> :default

Задать путь полезно, чтобы Elixir знал, что только определенные пути в большой конфигурации зависят от времени компиляции.

compile_env(env, app, key_or_path, default)Source

@spec compile_env(Macro.Env.t(), app(), key() | list(), value()) :: value()

Считывает среду приложения во время компиляции из макроса.

Как правило, разработчики будут использовать compile_env/3. Эта функция должна вызываться только из макросов, которые предназначены для динамического чтения среды компиляции.

Она ожидает Macro.Env в качестве первого аргумента, где Macro.Env обычно является __CALLER__ в макросе. Она вызывает исключение, если Macro.Env поступает из функции.

compile_env!(app, key_or_path)Source

@spec compile_env!(app(), key() | list()) :: value()

Считывает среду приложения во время компиляции или вызывает исключение.

Это то же самое, что и compile_env/3, но она вызывает ArgumentError, если конфигурация недоступна.

compile_env!(env, app, key_or_path)Source

@spec compile_env!(Macro.Env.t(), app(), key() | list()) :: value()

Считывает среду приложения во время компиляции из макроса или вызывает исключение.

Как правило, разработчики будут использовать compile_env!/2. Эта функция должна вызываться только из макросов, которые предназначены для динамического чтения среды компиляции.

Она ожидает Macro.Env в качестве первого аргумента, где Macro.Env обычно является __CALLER__ в макросе. Она вызывает исключение, если Macro.Env поступает из функции.

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

@spec delete_env(app(), key(), timeout: timeout(), persistent: boolean()) :: :ok

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

Она принимает те же параметры, что и put_env/4. Возвращает :ok.

ensure_all_started(app, type \\ :temporary)Source

@spec ensure_all_started(app(), restart_type()) ::
  {:ok, [app()]} | {:error, {app(), term()}}

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

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

ensure_loaded(app)Source

@spec ensure_loaded(app()) :: :ok | {:error, term()}

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

То же самое, что и load/1, но возвращает :ok, если приложение уже было загружено.

ensure_started(app, type \\ :temporary)Source

@spec ensure_started(app(), restart_type()) :: :ok | {:error, term()}

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

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

:ok = Application.ensure_started(:my_test_dep)

fetch_env(app, key)Source

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

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

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

Важно: вы должны использовать эту функцию для чтения только своей собственной среды приложения. Не читайте среду других приложений.

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

fetch_env!(app, key)Source

@spec fetch_env!(app(), key()) :: value()

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

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

Важно: вы должны использовать эту функцию для чтения только своей собственной среды приложения. Не читайте среду других приложений.

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

format_error(reason)Source

@spec format_error(any()) :: String.t()

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

get_all_env(app)Source

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

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

get_application(module)Source

@spec get_application(atom()) :: atom() | nil

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

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

get_env(app, key, default \\ nil)Source

@spec get_env(app(), key(), value()) :: value()

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

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

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

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

Примеры

get_env/3 обычно используется для чтения конфигурации ваших OTP-приложений. Поскольку конфигурации Mix обычно используются для настройки приложений, мы будем использовать это в качестве примера.

Рассмотрим новое приложение :my_app. :my_app содержит движок базы данных, который поддерживает пул баз данных. Движку базы данных необходима конфигурация для каждой из этих баз данных, и эта конфигурация предоставляется парами ключ-значение в среде :my_app.

config :my_app, Databases.RepoOne,
  # A database configuration
  ip: "localhost",
  port: 5433

config :my_app, Databases.RepoTwo,
  # Another database configuration (for the same OTP app)
  ip: "localhost",
  port: 20717

config :my_app, my_app_databases: [Databases.RepoOne, Databases.RepoTwo]

Наш движок базы данных, используемый :my_app, должен знать, какие базы данных существуют и каковы их конфигурации. Движок базы данных может вызвать Application.get_env(:my_app, :my_app_databases, []) для получения списка баз данных (указанных именами модулей).

Затем движок может перебрать каждый репозиторий в списке и вызвать Application.get_env(:my_app, Databases.RepoOne) и так далее, чтобы получить конфигурацию каждого из них. В этом случае каждая конфигурация будет списком ключевых слов, поэтому вы можете использовать функции в модуле Keyword или даже модуле Access для его обработки, например:

config = Application.get_env(:my_app, Databases.RepoOne)
config[:ip]

load(app)Source

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

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

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

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

loaded_applications()Source

@spec loaded_applications() :: [{app(), description :: charlist(), vsn :: charlist()}]

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

put_all_env(config, opts \\ [])Source

@spec put_all_env([{app(), [{key(), value()}]}],
  timeout: timeout(),
  persistent: boolean()
) :: :ok

Одновременно устанавливает среду для нескольких приложений.

Переданная конфигурация не должна:

  • содержать одно и то же приложение более одного раза
  • содержать один и тот же ключ внутри одного и того же приложения более одного раза

В противном случае произойдет ошибка.

Принимает те же параметры, что и put_env/4. Возвращает :ok.

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

@spec put_env(app(), key(), value(), timeout: timeout(), persistent: boolean()) :: :ok

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

Параметры

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

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

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

spec(app)Source

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

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

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

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

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

spec(app, key)Source

@spec spec(app(), application_key()) :: value() | nil

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

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

start(app, type \\ :temporary)Source

@spec start(app(), restart_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)Source

@spec started_applications(timeout()) :: [
  {app(), description :: charlist(), vsn :: charlist()}
]

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

stop(app)Source

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

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

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

unload(app)Source

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

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

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

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

Spec-Zone.ru

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