Включаемые приложения

Материал из Erlang по-русски.

(Перенаправлено с OTP Included Applications)
Оригинал этой статьи находится по адресу Included Applications

Перевод: К. Заборский

Дата: 12.11.2006

Версия: 1.0


Содержание

OTP design principles

Включаемые приложения

Определение

Приложение может включать другие приложения. У включаемого приложения есть свой каталог приложения и .app-файл, но оно запускается как часть дерева надзора другого приложения.

Приложение может быть включено только в одно другое приложение.

Включаемое приложение может включать другие приложения.

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

Первичное приложение и включаемые приложения
Первичное приложение и включаемые приложения

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

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

Указание включаемых приложений

Какие приложения должны быть включены, определяется ключом included_applications в .app-файле.

{application, prim_app,
 [{description, "Tree application"},
  {vsn, "1"},
  {modules, [prim_app_cb, prim_app_sup, prim_app_server]},
  {registered, [prim_app_server]},
  {included_applications, [incl_app]},
  {applications, [kernel, stdlib, sasl]},
  {mod, {prim_app_cb,[]}},
  {env, [{file, "/usr/local/log"}]}
 ]}.    

Синхронизация процессов при запуске

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

Фазы запуска определяются ключом start_phases в .app-файле, в котором содержится список туплов вида {Phase,PhaseArgs}, где переменная Phase - это некоторый атом, а PhaseArgs - терм. Помимо этого, значение ключа mod включающего приложения должно быть выставлено как {application_starter,[Module,StartArgs]}, где Module, как обычно - модуль обратного вызова приложения, а StartArgs - терм, передаваемый функции обратного вызова Module:start/2.

{application, prim_app,
 [{description, "Tree application"},
  {vsn, "1"},
  {modules, [prim_app_cb, prim_app_sup, prim_app_server]},
  {registered, [prim_app_server]},
  {included_applications, [incl_app]},
  {start_phases, [{init,[]}, {go,[]}]},
  {applications, [kernel, stdlib, sasl]},
  {mod, {application_starter,[prim_app_cb,[]]}},
  {env, [{file, "/usr/local/log"}]}
 ]}.
{application, incl_app,
 [{description, "Included application"},
  {vsn, "1"},
  {modules, [incl_app_cb, incl_app_sup, incl_app_server]},
  {registered, []},
  {start_phases, [{go,[]}]},
  {applications, [kernel, stdlib, sasl]},
  {mod, {incl_app_cb,[]}}
 ]}.  

При запуске первичного приложения вместе с включаемыми приложениями, первичное приложение запускается обычным образом: контроллер приложения создаёт владельца приложения, и владелец приложения вызывает Module:start(normal, StartArgs) для запуска супервайзора.

Затем, для первичного приложения и каждого включаемого приложения, в порядке сверху вниз и слева направо, владелец приложения вызывает Module:start_phase(Phase, Type, PhaseArgs) для каждой фазы, определённой для этого приложения и для первичного приложения ???. Заметьте также, что, если фаза не определена для включаемого приложения, функция не будет вызвана для этой фазы и для этого приложения.

Ниже следующие требования предъявляются к .app-файлу включаемого приложения:

  • Параметр {mod, {Module,StartArgs}} должен быть указан. Этот параметр используется для нахождения модуля обратного вызова Module для приложения. Переменная StartArgs игнорируется, т.к. функция Module:start/2 вызывается только для первичного приложения.
  • Если включаемое приложение само включает приложения, должен быть указан параметр{mod, {application_starter, [Module,StartArgs]}} вместо предыдущего.
  • Параметр {start_phases, [{Phase,PhaseArgs}]} должен быть указан, и множество указанных фаз должно быть подмножеством фаз, указанных для первичного приложения.

При запуске prim_app, которое было описано выше, контролллер приложения вызовет следующие функции обратного вызова до того, как application:start(prim_app) вернёт значение:

application:start(prim_app)
 => prim_app_cb:start(normal, [])
 => prim_app_cb:start_phase(init, normal, [])
 => prim_app_cb:start_phase(go, normal, [])
 => incl_app_cb:start_phase(go, normal, [])
ok