Reputation: 61121
I'm using rebar3 to produce a release, but how do I initialize mnesia on production?
If I write an "install" escript that does the mnesia:create_schema([node()])
- it will use a completely different node name from the one that release uses.
So I end up creating a schema for "nonode@nonode" while production mnesia when I start my app with my-app-1.0.0 start
tries to access "myapp@localhost" node.
Also, it is kind of a chicken-and-egg problem:
node()
name as the app will use).Just wandering if there is a good way to handle this?
Here is my install escript that I run independently:
#!/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}]).
P.S.: I am using rebar3
which uses relx
to build releases.
Upvotes: 3
Views: 1230
Reputation: 8340
I am using my own build system which was written mainly because of that exact requirement - ability to install and initialize a node before starting it. The idea is quite simple: there are two releases, in this particular example called cmd
and humbundee
. The cmd
release doesn't start the main applications, only loads them. Then a special function is executed to initialize the node. The function is configured in the reltool.config
file. In this case it's hbd_setup
from the deploy
application. That function reads the configuration file and either creates and initializes the mnesia database from a backup or creates a new database if the backup doesn't exist. Once the node is installed it's started using the proper release. The same steps are executed in development (directly from the source code) and in production (from an OTP release).
With that setup the problem you described doesn't exist because both releases are started from the same location, using almost the same command and configuration files (builderl
generates them from the configuration in reltool.config
).
You could employ the same idea with any build tool, including rebar3
and relx
, by executing these steps manually or with some sort of a script.
What builderl
does is that it executes these steps automatically and provides an environment to execute them in the same way in development and production, e.g. see the bottom of the humbundee
project's README file:
Install the node. This will start the cmd
release and execute the hbd_setup:install/2
function to initialize the node:
./bin/init.esh
Start the node. This will start the humbundee
release, which starts all applications with their corresponding supervisor trees:
./bin/start.esh
builderl
actually uses rebar
to pull and compile dependencies that depend on other projects, however it uses only OTP to create the release. It can also download dependencies itself using a project-wide dependency file, which are then compiled with make
(compiling without the make
is work in progress). I hope that helps.
Upvotes: 1