Question

I have some apps in my cluster, I need to start some of them sometimes on different hosts.

The story is that the Erlang cluster is already running, so even though I have my .app resource file per application stating which applications should be started before mine, this only works to create a startup script, not to start an app in a already running node.

At the moment I have a custom routine that uses application:get_key(Application,applications) to extract the dependencies and start them separately before starting the given application.

I was wondering if there isn't a better way of doing this.

Was it helpful?

Solution

When starting the app outside of the startup script you do need to start the dependencies first. You could build the smarts to do this into the app itself so that when the app starts it will start any required dependencies before it needs them.

One place I've seen this done is in Mochiweb apps. The default app templates include code for loading dependencies on startup:

-module(some_app).
-export([start/0, stop/0]).

ensure_started(App) ->
    case application:start(App) of
        ok ->
            ok;
        {error, {already_started, App}} ->
            ok
    end.

%% @spec start() -> ok
%% @doc Start the some_app server.
start() ->
    some_app_deps:ensure(),
    ensure_started(crypto),
    application:start(some_app).

%% @spec stop() -> ok
%% @doc Stop the some_app server.
stop() ->
    application:stop(some_app).

OTHER TIPS

Since Erlang R16B02, there is also application:ensure_all_started.

Frankly, the standard tools for doing this in Erlang are unnecessarily annoying right now. I tend to put the following boiler-plate in my application callback module:

-module(myapp_app).
-export([start/0]).

start() -> a_start(myapp, permanent).

a_start(App, Type) ->
    start_ok(App, Type, application:start(App, Type)).

start_ok(_App, _Type, ok) -> ok;
start_ok(_App, _Type, {error, {already_started, _App}}) -> ok;
start_ok(App, Type, {error, {not_started, Dep}}) ->
    ok = a_start(Dep, Type),
    a_start(App, Type);
start_ok(App, _Type, {error, Reason}) ->
    erlang:error({app_start_failed, App, Reason}).

You can then add -s myapp_app to your erlang command line and this will start the app and all its dependencies recursively. Why this function isn't in the application module I don't know :)


There is a working example of this custom erlang app startup code in my Erlang Factory 2012 SFBay example app.

If you write your app under "OTP Design Principles", you will have to make yourappname.app file, which will contains `applications' section. This section defines which other applications you want to be started before yours. Here is stated:

applications

All applications which must be started before this application is started. systools uses this list to generate correct boot scripts. Defaults to [], but note that all applications have dependencies to at least kernel and stdlib.

So if you use releases, this dependency resolution will be solved by systools.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top