Что такое Application и как оно инициализируется?

В Elixir Application — это специальный модуль, который служит точкой входа для запуска и управления жизненным циклом вашего проекта. Он предоставляет инфраструктуру для запуска процессов (обычно через Supervisor), настройки конфигурации и управления зависимостями между компонентами.

Основные цели Application

  1. **Определение точки входа в систему.
    **
  2. **Инициализация дерева процессов (обычно Supervisor-дерево).
    **
  3. **Загрузка конфигурации.
    **
  4. **Автоматический запуск при старте системы или релиза.
    **
  5. **Возможность использовать mix release и запуск как службы.
    **

Структура Application

Чтобы создать полноценное OTP-приложение, в Elixir нужно:

  1. Добавить модуль, реализующий поведение Application.

  2. Реализовать колбэк start/2.

  3. Указать модуль в mix.exs.

Пример реализации модуля приложения

defmodule MyApp.Application do
use Application
@impl true
def start(\_type, \_args) do
children = \[
{MyApp.Worker, arg}
\]
opts = \[strategy: :one_for_one, name: MyApp.Supervisor\]
Supervisor.start_link(children, opts)
end
end
  • children — список процессов, которые нужно запустить.

  • Supervisor.start_link/2 — инициализирует дерево процессов.

  • opts[:strategy] — стратегия перезапуска (например, :one_for_one).

Объяснение аргументов start/2

  • start/2 вызывается при запуске приложения.

  • Первый аргумент type может принимать значения:

    • :normal — обычный запуск.

    • :takeover — запуск при восстановлении после сбоя.

    • :failover — при передаче управления в кластерной системе.

  • Второй аргумент args передаётся при запуске приложения (например, через mix или release).

Указание Application в mix.exs

Файл mix.exs должен содержать ссылку на модуль приложения:

defmodule MyApp.MixProject do
use Mix.Project
def application do
\[
mod: {MyApp.Application, \[\]},
extra_applications: \[:logger\]
\]
end
end
  • mod: {MyApp.Application, []} — указывает, какой модуль вызывать при старте.

  • extra_applications — список зависимостей, запускаемых вместе с вашим приложением (например, :logger, :crypto и т.д.).

Пример рабочего проекта

mix new my_app --sup

Опция --sup автоматически создаёт структуру с Supervisor и Application.

В lib/my_app/application.ex будет уже готовая заготовка Application.

Поведение при остановке

Elixir/OTP предоставляет механизм остановки приложения:

Application.stop(:my_app)

Также вызывается колбэк stop/1, если он реализован:

@impl true
def stop(\_state) do
\# Очистка ресурсов, запись логов и т.д.
:ok
end

Запуск приложения вручную (без Mix)

Если проект собран в .beam и запущен в iex, то приложение можно запустить:

Application.ensure_all_started(:my_app)

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

Примеры из реальных приложений

Phoenix:

В Phoenix веб-приложениях Application инициализирует веб-сервер, Ecto (базу данных), PubSub и прочее:

children = \[
MyApp.Repo,
MyAppWeb.Endpoint
\]

Nerves:

В Nerves-проектах Application может инициализировать работу с железом, портами и контроллерами.

Работа с конфигурацией приложения

Конфигурация задаётся в config/config.exs, и доступна через:

Application.get_env(:my_app, :key)

Также можно задать переменные в runtime.exs для поддержки mix release:

config :my_app, :api_key, System.get_env("MY_APP_API_KEY")

Зависимости и lifecycle

Если приложение зависит от других библиотек, они автоматически поднимаются при старте, если указаны в mix.exs → applications.

Для инициализации сторонних зависимостей используется Application.ensure_all_started/1.

Связь с Supervisor-деревом

Точка входа в Application.start/2 всегда должна запускать Supervisor — даже если приложение запускает только один процесс. Это основа отказоустойчивости, масштабируемости и структуры Elixir-программ.

Application — фундаментальная абстракция в Elixir/OTP, объединяющая процессы, конфигурацию и контроль жизненного цикла.