Как вы инициализируете Mnesia на производстве?
Я использую rebar3 для создания релиза, но как мне инициализировать Mnesia на производстве?
Если я напишу "установить" сценарий, который делает mnesia:create_schema([node()])
- он будет использовать совершенно другое имя узла, чем то, которое использует релиз.
Поэтому я в конечном итоге создаю схему для "nonode @ nonode" во время производственной mnesia, когда я запускаю свое приложение с my-app-1.0.0 start
пытается получить доступ к узлу "myapp @ localhost".
Кроме того, это своего рода проблема курицы и яйца:
- Я не могу запустить свое приложение без таблиц Mnesia
- Я не могу установить свои таблицы Mnesia без моего приложения (как то же самое
node()
имя, как приложение будет использовать).
Просто бродить, если есть хороший способ справиться с этим?
Вот мой установочный escript, который я запускаю самостоятельно:
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable ls-mnesia debug verbose
-include("../include/rr.hrl").
main(_) ->
application:set_env(mnesia, dir, "/usr/local/src/db/mnesia"),
application:stop(mnesia),
install([node()|nodes()]).
install(Nodes) ->
case mnesia:create_schema(Nodes) of
ok ->
rpc:multicall(Nodes, application, start, [mnesia]),
read_store_create_tables(Nodes),
event_store_create_tables(Nodes),
rpc:multicall(Nodes, application, stop, [mnesia]);
Err ->
error_logger:warning_msg("Could not create schema: ~p~n", [Err]),
Err
end.
event_store_create_tables(Nodes) ->
{_, ok} = mnesia:create_table(rr_events,
[{attributes, record_info(fields, rr_events)},
{disc_copies, Nodes},
{type, bag}]).
read_store_create_tables(Nodes) ->
% Initialize the actual data-tables for the projections
{_, ok} = mnesia:create_table(rr_competencies,
[{attributes, record_info(fields, rr_competencies)},
{disc_copies, Nodes}]).
PS: я использую rebar3
который использует relx
строить релизы.
1 ответ
Я использую свою собственную систему сборки, которая была написана в основном из-за того точного требования - возможность установить и инициализировать узел перед его запуском. Идея довольно проста: есть два выпуска, в данном конкретном примере cmd
а также humbundee
, cmd
релиз не запускает основные приложения, только загружает их. Затем выполняется специальная функция для инициализации узла. Функция настроена в reltool.config
файл. В этом случае это hbd_setup
от deploy
приложение. Эта функция читает файл конфигурации и либо создает и инициализирует базу данных mnesia из резервной копии, либо создает новую базу данных, если резервная копия не существует. Как только узел установлен, он запускается с использованием правильной версии. Те же шаги выполняются в разработке (непосредственно из исходного кода) и в производстве (из выпуска OTP).
При такой настройке описанная вами проблема не существует, поскольку оба выпуска запускаются из одного и того же местоположения, используя почти одинаковые файлы команд и конфигурации (builderl
генерирует их из конфигурации в reltool.config
).
Вы можете использовать ту же идею с любым инструментом сборки, в том числе rebar3
а также relx
выполнив эти шаги вручную или с помощью какого-либо сценария.
Какие builderl
делает то, что он выполняет эти шаги автоматически и предоставляет среду для их выполнения в процессе разработки и производства, например, см. нижнюю часть humbundee
Файл README проекта:
Установите узел. Это начнет cmd
отпустить и выполнить hbd_setup:install/2
Функция для инициализации узла:
./bin/init.esh
Запустите узел. Это начнет humbundee
release, который запускает все приложения с соответствующими им деревьями супервизора:
./bin/start.esh
builderl
на самом деле использует rebar
извлекать и компилировать зависимости, которые зависят от других проектов, однако для создания выпуска используется только OTP. Он также может загружать зависимости самостоятельно, используя файл зависимостей всего проекта, который затем компилируется с make
(составление без make
идет работа). Надеюсь, это поможет.