2016-04-22 72 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