|
@@ -21,17 +21,8 @@
|
|
|
, is_ready/0
|
|
, is_ready/0
|
|
|
]).
|
|
]).
|
|
|
|
|
|
|
|
--export([ stop_apps/1
|
|
|
|
|
- , ensure_apps_started/0
|
|
|
|
|
- ]).
|
|
|
|
|
-
|
|
|
|
|
--export([sorted_reboot_apps/0]).
|
|
|
|
|
-
|
|
|
|
|
--ifdef(TEST).
|
|
|
|
|
--export([sorted_reboot_apps/1]).
|
|
|
|
|
--endif.
|
|
|
|
|
-
|
|
|
|
|
-include_lib("emqx/include/logger.hrl").
|
|
-include_lib("emqx/include/logger.hrl").
|
|
|
|
|
+-include_lib("emqx/include/emqx.hrl").
|
|
|
|
|
|
|
|
%% @doc EMQ X boot entrypoint.
|
|
%% @doc EMQ X boot entrypoint.
|
|
|
start() ->
|
|
start() ->
|
|
@@ -45,14 +36,10 @@ start() ->
|
|
|
ok = print_otp_version_warning(),
|
|
ok = print_otp_version_warning(),
|
|
|
|
|
|
|
|
ok = load_config_files(),
|
|
ok = load_config_files(),
|
|
|
-
|
|
|
|
|
- ok = ensure_apps_started(),
|
|
|
|
|
-
|
|
|
|
|
- _ = emqx_plugins:load(),
|
|
|
|
|
-
|
|
|
|
|
- ok = print_vsn(),
|
|
|
|
|
-
|
|
|
|
|
- ok = start_autocluster().
|
|
|
|
|
|
|
+ %% Load application first for ekka_mnesia scanner
|
|
|
|
|
+ ekka:start(),
|
|
|
|
|
+ ok = ekka_rlog:wait_for_shards(?EMQX_SHARDS, infinity),
|
|
|
|
|
+ ok.
|
|
|
|
|
|
|
|
graceful_shutdown() ->
|
|
graceful_shutdown() ->
|
|
|
emqx_machine_terminator:graceful_wait().
|
|
emqx_machine_terminator:graceful_wait().
|
|
@@ -74,13 +61,6 @@ print_otp_version_warning() ->
|
|
|
[?OTP_RELEASE]).
|
|
[?OTP_RELEASE]).
|
|
|
-endif. % OTP_RELEASE > 22
|
|
-endif. % OTP_RELEASE > 22
|
|
|
|
|
|
|
|
--ifdef(TEST).
|
|
|
|
|
-print_vsn() -> ok.
|
|
|
|
|
--else. % TEST
|
|
|
|
|
-print_vsn() ->
|
|
|
|
|
- ?ULOG("~s ~s is running now!~n", [emqx_app:get_description(), emqx_app:get_release()]).
|
|
|
|
|
--endif. % TEST
|
|
|
|
|
-
|
|
|
|
|
load_config_files() ->
|
|
load_config_files() ->
|
|
|
%% the app env 'config_files' for 'emqx` app should be set
|
|
%% the app env 'config_files' for 'emqx` app should be set
|
|
|
%% in app.time.config by boot script before starting Erlang VM
|
|
%% in app.time.config by boot script before starting Erlang VM
|
|
@@ -89,114 +69,3 @@ load_config_files() ->
|
|
|
ok = emqx_config:init_load(emqx_machine_schema, ConfFiles),
|
|
ok = emqx_config:init_load(emqx_machine_schema, ConfFiles),
|
|
|
%% to avoid config being loaded again when emqx app starts.
|
|
%% to avoid config being loaded again when emqx app starts.
|
|
|
ok = emqx_app:set_init_config_load_done().
|
|
ok = emqx_app:set_init_config_load_done().
|
|
|
-
|
|
|
|
|
-start_autocluster() ->
|
|
|
|
|
- ekka:callback(prepare, fun ?MODULE:stop_apps/1),
|
|
|
|
|
- ekka:callback(reboot, fun ?MODULE:ensure_apps_started/0),
|
|
|
|
|
- _ = ekka:autocluster(emqx), %% returns 'ok' or a pid or 'any()' as in spec
|
|
|
|
|
- ok.
|
|
|
|
|
-
|
|
|
|
|
-stop_apps(Reason) ->
|
|
|
|
|
- ?SLOG(info, #{msg => "stopping_apps", reason => Reason}),
|
|
|
|
|
- _ = emqx_alarm_handler:unload(),
|
|
|
|
|
- lists:foreach(fun stop_one_app/1, lists:reverse(sorted_reboot_apps())).
|
|
|
|
|
-
|
|
|
|
|
-stop_one_app(App) ->
|
|
|
|
|
- ?SLOG(debug, #{msg => "stopping_app", app => App}),
|
|
|
|
|
- try
|
|
|
|
|
- _ = application:stop(App)
|
|
|
|
|
- catch
|
|
|
|
|
- C : E ->
|
|
|
|
|
- ?SLOG(error, #{msg => "failed_to_stop_app",
|
|
|
|
|
- app => App,
|
|
|
|
|
- exception => C,
|
|
|
|
|
- reason => E})
|
|
|
|
|
- end.
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-ensure_apps_started() ->
|
|
|
|
|
- lists:foreach(fun start_one_app/1, sorted_reboot_apps()).
|
|
|
|
|
-
|
|
|
|
|
-start_one_app(App) ->
|
|
|
|
|
- ?SLOG(debug, #{msg => "starting_app", app => App}),
|
|
|
|
|
- case application:ensure_all_started(App) of
|
|
|
|
|
- {ok, Apps} ->
|
|
|
|
|
- ?SLOG(debug, #{msg => "started_apps", apps => Apps});
|
|
|
|
|
- {error, Reason} ->
|
|
|
|
|
- ?SLOG(critical, #{msg => "failed_to_start_app", app => App, reason => Reason}),
|
|
|
|
|
- error({failed_to_start_app, App, Reason})
|
|
|
|
|
- end.
|
|
|
|
|
-
|
|
|
|
|
-%% list of app names which should be rebooted when:
|
|
|
|
|
-%% 1. due to static static config change
|
|
|
|
|
-%% 2. after join a cluster
|
|
|
|
|
-reboot_apps() ->
|
|
|
|
|
- [ gproc
|
|
|
|
|
- , esockd
|
|
|
|
|
- , ranch
|
|
|
|
|
- , cowboy
|
|
|
|
|
- , emqx
|
|
|
|
|
- , emqx_prometheus
|
|
|
|
|
- , emqx_modules
|
|
|
|
|
- , emqx_dashboard
|
|
|
|
|
- , emqx_connector
|
|
|
|
|
- , emqx_gateway
|
|
|
|
|
- , emqx_statsd
|
|
|
|
|
- , emqx_resource
|
|
|
|
|
- , emqx_rule_engine
|
|
|
|
|
- , emqx_bridge
|
|
|
|
|
- , emqx_bridge_mqtt
|
|
|
|
|
- , emqx_plugin_libs
|
|
|
|
|
- , emqx_management
|
|
|
|
|
- , emqx_retainer
|
|
|
|
|
- , emqx_exhook
|
|
|
|
|
- , emqx_authn
|
|
|
|
|
- , emqx_authz
|
|
|
|
|
- , emqx_psk
|
|
|
|
|
- ].
|
|
|
|
|
-
|
|
|
|
|
-sorted_reboot_apps() ->
|
|
|
|
|
- Apps = [{App, app_deps(App)} || App <- reboot_apps()],
|
|
|
|
|
- sorted_reboot_apps(Apps).
|
|
|
|
|
-
|
|
|
|
|
-app_deps(App) ->
|
|
|
|
|
- case application:get_key(App, applications) of
|
|
|
|
|
- undefined -> [];
|
|
|
|
|
- {ok, List} -> lists:filter(fun(A) -> lists:member(A, reboot_apps()) end, List)
|
|
|
|
|
- end.
|
|
|
|
|
-
|
|
|
|
|
-sorted_reboot_apps(Apps) ->
|
|
|
|
|
- G = digraph:new(),
|
|
|
|
|
- try
|
|
|
|
|
- lists:foreach(fun({App, Deps}) -> add_app(G, App, Deps) end, Apps),
|
|
|
|
|
- case digraph_utils:topsort(G) of
|
|
|
|
|
- Sorted when is_list(Sorted) ->
|
|
|
|
|
- Sorted;
|
|
|
|
|
- false ->
|
|
|
|
|
- Loops = find_loops(G),
|
|
|
|
|
- error({circular_application_dependency, Loops})
|
|
|
|
|
- end
|
|
|
|
|
- after
|
|
|
|
|
- digraph:delete(G)
|
|
|
|
|
- end.
|
|
|
|
|
-
|
|
|
|
|
-add_app(G, App, undefined) ->
|
|
|
|
|
- ?SLOG(debug, #{msg => "app_is_not_loaded", app => App}),
|
|
|
|
|
- %% not loaded
|
|
|
|
|
- add_app(G, App, []);
|
|
|
|
|
-add_app(_G, _App, []) ->
|
|
|
|
|
- ok;
|
|
|
|
|
-add_app(G, App, [Dep | Deps]) ->
|
|
|
|
|
- digraph:add_vertex(G, App),
|
|
|
|
|
- digraph:add_vertex(G, Dep),
|
|
|
|
|
- digraph:add_edge(G, Dep, App), %% dep -> app as dependency
|
|
|
|
|
- add_app(G, App, Deps).
|
|
|
|
|
-
|
|
|
|
|
-find_loops(G) ->
|
|
|
|
|
- lists:filtermap(
|
|
|
|
|
- fun (App) ->
|
|
|
|
|
- case digraph:get_short_cycle(G, App) of
|
|
|
|
|
- false -> false;
|
|
|
|
|
- Apps -> {true, Apps}
|
|
|
|
|
- end
|
|
|
|
|
- end, digraph:vertices(G)).
|
|
|