2016-04-22 86 views
2

我正在使用rebar3来制作发行版,但是如何初始化生产中的mnesia?如何初始化生产中的mnesia?

如果我编写一个执行mnesia:create_schema([node()])的“安装”脚本,它将使用与发行版使用的完全不同的节点名称。

因此,我最终创建了一个“nonode @ nonode”模式,而生产mnesia时,当我启动我的应用程序my-app-1.0.0 start时,它尝试访问“myapp @ localhost”节点。

而且,这是一种先有鸡还是先有蛋的问题:

  1. 我无法启动我的应用程序,而不Mnesia表
  2. 我不能没有我的应用程序运行安装我的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}]). 

P.S:我使用rebar3它使用relx打造的版本。

回答

1

我用我自己的build system这主要是书面的,因为确切的要求 - 安装和启动前初始化一个节点的能力。这个想法很简单:有two releases,在这个特殊的例子叫做cmdhumbundeecmd版本不启动主应用程序,只加载它们。然后执行一个特殊的函数来初始化节点。该功能在reltool.config文件中配置。在这种情况下,它是deploy应用程序中的hbd_setup。该函数读取配置文件,并从备份创建和初始化mnesia数据库,或者如果备份不存在,则创建新的数据库。一旦节点安装完成,它就开始使用正确的版本。开发(直接从源代码)和生产(从OTP版本开始)执行相同的步骤。

使用该设置,您描述的问题不存在,因为两个版本都使用几乎相同的命令和配置文件(builderlreltool.config中的配置生成它们)从相同的位置启动。


你可以采用同样的想法与任何构建工具,包括rebar3relx,通过手动或使用某种脚本的执行这些步骤。

做什么builderl的是,它会自动执行这些步骤,并提供了一个环境,以同样的方式开发和生产中,如执行它们看到bottom of the humbundee project's README文件:

安装节点。这将启动cmd发布并执行hbd_setup:install/2函数初始化节点:

./bin/init.esh 

启动的节点。这将启动humbundee释放,这与它们对应的主管树木开始所有的应用程序:

./bin/start.esh 

builderl实际使用rebar拉和编译dependencies that depend on other projects,但它仅使用OTP创建释放。它也可以使用project-wide dependency file自己下载依赖项,然后是compiled with make(编译时没有makework in progress)。我希望有所帮助。

+0

但是,你如何处理使这个全自动通过构建脚本(即ansible)?问题在于,应用程序启动时不像脚本,而是作为服务运行 - 所以脚本不知道应用程序何时初始化数据库。 (哇,这是比我想象的更复杂。) – drozzy

+0

请检查此答案(搜索'init:stop()'):http://stackoverflow.com/questions/36359040/idiomatic-way-to-ship-命令行工具写入erlang/36362156#36362156然后这个函数:https://github.com/yoonka/builderl/blob/master/src/bld_init.erl#L902基本上,有两个Erlang实例。执行'./bin/init.esh'时,'builderl'运行在它自己的VM中。然后它使用'cmd'释放启动已安装的VM,配置它,然后关闭它。如果出现错误,它将返回代码'1'。当'builderl'完成它的返回代码时,可以通过'make'或其他脚本来检查。 – Amiramix