|
|
@@ -11,10 +11,13 @@
|
|
|
-include_lib("stdlib/include/qlc.hrl").
|
|
|
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
|
|
|
|
|
|
+-behaviour(gen_statem).
|
|
|
+
|
|
|
-export([
|
|
|
start_link/0,
|
|
|
enable/1,
|
|
|
enable/2,
|
|
|
+ enable/3,
|
|
|
disable/1,
|
|
|
disable/2,
|
|
|
status/0
|
|
|
@@ -22,13 +25,13 @@
|
|
|
|
|
|
-export([
|
|
|
init/1,
|
|
|
- handle_call/3,
|
|
|
- handle_info/2,
|
|
|
- handle_cast/2,
|
|
|
- code_change/3
|
|
|
+ callback_mode/0,
|
|
|
+ handle_event/4,
|
|
|
+ code_change/4
|
|
|
]).
|
|
|
|
|
|
-define(ENABLE_KIND, emqx_node_rebalance).
|
|
|
+-define(SERVER_REFERENCE, undefined).
|
|
|
|
|
|
%%--------------------------------------------------------------------
|
|
|
%% APIs
|
|
|
@@ -38,16 +41,21 @@
|
|
|
|
|
|
-spec start_link() -> startlink_ret().
|
|
|
start_link() ->
|
|
|
- gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
|
|
+ gen_statem:start_link({local, ?MODULE}, ?MODULE, [], []).
|
|
|
|
|
|
-spec enable(pid()) -> ok_or_error(already_enabled | eviction_agent_busy).
|
|
|
enable(CoordinatorPid) ->
|
|
|
enable(CoordinatorPid, ?ENABLE_KIND).
|
|
|
|
|
|
-spec enable(pid(), emqx_eviction_agent:kind()) ->
|
|
|
- ok_or_error(already_enabled | eviction_agent_busy).
|
|
|
+ ok_or_error(invalid_coordinator | eviction_agent_busy).
|
|
|
enable(CoordinatorPid, Kind) ->
|
|
|
- gen_server:call(?MODULE, {enable, CoordinatorPid, Kind}).
|
|
|
+ enable(CoordinatorPid, Kind, emqx_eviction_agent:default_options()).
|
|
|
+
|
|
|
+-spec enable(pid(), emqx_eviction_agent:kind(), emqx_eviction_agent:options()) ->
|
|
|
+ ok_or_error(invalid_coordinator | eviction_agent_busy).
|
|
|
+enable(CoordinatorPid, Kind, Options) ->
|
|
|
+ gen_statem:call(?MODULE, {enable, CoordinatorPid, Kind, Options}).
|
|
|
|
|
|
-spec disable(pid()) -> ok_or_error(already_disabled | invalid_coordinator).
|
|
|
disable(CoordinatorPid) ->
|
|
|
@@ -56,88 +64,113 @@ disable(CoordinatorPid) ->
|
|
|
-spec disable(pid(), emqx_eviction_agent:kind()) ->
|
|
|
ok_or_error(already_disabled | invalid_coordinator).
|
|
|
disable(CoordinatorPid, Kind) ->
|
|
|
- gen_server:call(?MODULE, {disable, CoordinatorPid, Kind}).
|
|
|
+ gen_statem:call(?MODULE, {disable, CoordinatorPid, Kind}).
|
|
|
|
|
|
-spec status() -> status().
|
|
|
status() ->
|
|
|
- gen_server:call(?MODULE, status).
|
|
|
+ gen_statem:call(?MODULE, status).
|
|
|
|
|
|
%%--------------------------------------------------------------------
|
|
|
-%% gen_server callbacks
|
|
|
+%% gen_statem callbacks
|
|
|
%%--------------------------------------------------------------------
|
|
|
|
|
|
+-define(disabled, disabled).
|
|
|
+-define(enabled(ST), {enabled, ST}).
|
|
|
+
|
|
|
+callback_mode() ->
|
|
|
+ handle_event_function.
|
|
|
+
|
|
|
init([]) ->
|
|
|
- {ok, #{}}.
|
|
|
-
|
|
|
-handle_call({enable, CoordinatorPid, Kind}, _From, St) ->
|
|
|
- case St of
|
|
|
- #{coordinator_pid := _Pid} ->
|
|
|
- {reply, {error, already_enabled}, St};
|
|
|
- _ ->
|
|
|
- true = link(CoordinatorPid),
|
|
|
- EvictionAgentPid = whereis(emqx_eviction_agent),
|
|
|
- true = link(EvictionAgentPid),
|
|
|
- case emqx_eviction_agent:enable(Kind, undefined) of
|
|
|
- ok ->
|
|
|
- {reply, ok, #{
|
|
|
- coordinator_pid => CoordinatorPid,
|
|
|
- eviction_agent_pid => EvictionAgentPid
|
|
|
- }};
|
|
|
- {error, eviction_agent_busy} ->
|
|
|
- true = unlink(EvictionAgentPid),
|
|
|
- true = unlink(CoordinatorPid),
|
|
|
- {reply, {error, eviction_agent_busy}, St}
|
|
|
- end
|
|
|
- end;
|
|
|
-handle_call({disable, CoordinatorPid, Kind}, _From, St) ->
|
|
|
- case St of
|
|
|
- #{
|
|
|
- coordinator_pid := CoordinatorPid,
|
|
|
- eviction_agent_pid := EvictionAgentPid
|
|
|
- } ->
|
|
|
- _ = emqx_eviction_agent:disable(Kind),
|
|
|
+ {ok, ?disabled, #{}}.
|
|
|
+
|
|
|
+%% disabled status
|
|
|
+
|
|
|
+%% disabled status, enable command
|
|
|
+handle_event({call, From}, {enable, CoordinatorPid, Kind, Options}, ?disabled, Data) ->
|
|
|
+ true = link(CoordinatorPid),
|
|
|
+ EvictionAgentPid = whereis(emqx_eviction_agent),
|
|
|
+ true = link(EvictionAgentPid),
|
|
|
+ case emqx_eviction_agent:enable(Kind, ?SERVER_REFERENCE, Options) of
|
|
|
+ ok ->
|
|
|
+ {next_state,
|
|
|
+ ?enabled(#{
|
|
|
+ coordinator_pid => CoordinatorPid,
|
|
|
+ eviction_agent_pid => EvictionAgentPid,
|
|
|
+ kind => Kind
|
|
|
+ }), Data, {reply, From, ok}};
|
|
|
+ {error, eviction_agent_busy} ->
|
|
|
true = unlink(EvictionAgentPid),
|
|
|
true = unlink(CoordinatorPid),
|
|
|
- NewSt = maps:without(
|
|
|
- [coordinator_pid, eviction_agent_pid],
|
|
|
- St
|
|
|
- ),
|
|
|
- {reply, ok, NewSt};
|
|
|
- #{coordinator_pid := _CoordinatorPid} ->
|
|
|
- {reply, {error, invalid_coordinator}, St};
|
|
|
- #{} ->
|
|
|
- {reply, {error, already_disabled}, St}
|
|
|
+ {keep_state_and_data, {reply, From, {error, eviction_agent_busy}}}
|
|
|
end;
|
|
|
-handle_call(status, _From, St) ->
|
|
|
- case St of
|
|
|
- #{coordinator_pid := Pid} ->
|
|
|
- {reply, {enabled, Pid}, St};
|
|
|
- _ ->
|
|
|
- {reply, disabled, St}
|
|
|
- end;
|
|
|
-handle_call(Msg, _From, St) ->
|
|
|
+%% disabled status, disable command
|
|
|
+handle_event({call, From}, {disable, _CoordinatorPid, _Kind}, ?disabled, _Data) ->
|
|
|
+ {keep_state_and_data, {reply, From, {error, already_disabled}}};
|
|
|
+%% disabled status, status command
|
|
|
+handle_event({call, From}, status, ?disabled, _Data) ->
|
|
|
+ {keep_state_and_data, {reply, From, disabled}};
|
|
|
+%% enabled status
|
|
|
+
|
|
|
+%% enabled status, enable command
|
|
|
+handle_event(
|
|
|
+ {call, From},
|
|
|
+ {enable, CoordinatorPid, Kind, Options},
|
|
|
+ ?enabled(#{
|
|
|
+ coordinator_pid := CoordinatorPid,
|
|
|
+ kind := Kind
|
|
|
+ }),
|
|
|
+ _Data
|
|
|
+) ->
|
|
|
+ %% just updating options
|
|
|
+ ok = emqx_eviction_agent:enable(Kind, ?SERVER_REFERENCE, Options),
|
|
|
+ {keep_state_and_data, {reply, From, ok}};
|
|
|
+handle_event({call, From}, {enable, _CoordinatorPid, _Kind, _Options}, ?enabled(_St), _Data) ->
|
|
|
+ {keep_state_and_data, {reply, From, {error, invalid_coordinator}}};
|
|
|
+%% enabled status, disable command
|
|
|
+handle_event(
|
|
|
+ {call, From},
|
|
|
+ {disable, CoordinatorPid, Kind},
|
|
|
+ ?enabled(#{
|
|
|
+ coordinator_pid := CoordinatorPid,
|
|
|
+ eviction_agent_pid := EvictionAgentPid
|
|
|
+ }),
|
|
|
+ Data
|
|
|
+) ->
|
|
|
+ _ = emqx_eviction_agent:disable(Kind),
|
|
|
+ true = unlink(EvictionAgentPid),
|
|
|
+ true = unlink(CoordinatorPid),
|
|
|
+ {next_state, ?disabled, Data, {reply, From, ok}};
|
|
|
+handle_event({call, From}, {disable, _CoordinatorPid, _Kind}, ?enabled(_St), _Data) ->
|
|
|
+ {keep_state_and_data, {reply, From, {error, invalid_coordinator}}};
|
|
|
+%% enabled status, status command
|
|
|
+handle_event({call, From}, status, ?enabled(#{coordinator_pid := CoordinatorPid}), _Data) ->
|
|
|
+ {keep_state_and_data, {reply, From, {enabled, CoordinatorPid}}};
|
|
|
+%% fallbacks
|
|
|
+
|
|
|
+handle_event({call, From}, Msg, State, Data) ->
|
|
|
?SLOG(warning, #{
|
|
|
msg => "unknown_call",
|
|
|
call => Msg,
|
|
|
- state => St
|
|
|
- }),
|
|
|
- {reply, ignored, St}.
|
|
|
-
|
|
|
-handle_info(Msg, St) ->
|
|
|
- ?SLOG(warning, #{
|
|
|
- msg => "unknown_info",
|
|
|
- info => Msg,
|
|
|
- state => St
|
|
|
+ state => State,
|
|
|
+ data => Data
|
|
|
}),
|
|
|
- {noreply, St}.
|
|
|
-
|
|
|
-handle_cast(Msg, St) ->
|
|
|
+ {keep_state_and_data, {reply, From, ignored}};
|
|
|
+handle_event(cast, Msg, State, Data) ->
|
|
|
?SLOG(warning, #{
|
|
|
msg => "unknown_cast",
|
|
|
cast => Msg,
|
|
|
- state => St
|
|
|
+ state => State,
|
|
|
+ data => Data
|
|
|
+ }),
|
|
|
+ keep_state_and_data;
|
|
|
+handle_event(info, Msg, State, Data) ->
|
|
|
+ ?SLOG(warning, #{
|
|
|
+ msg => "unknown_info",
|
|
|
+ info => Msg,
|
|
|
+ state => State,
|
|
|
+ data => Data
|
|
|
}),
|
|
|
- {noreply, St}.
|
|
|
+ keep_state_and_data.
|
|
|
|
|
|
-code_change(_Vsn, State, _Extra) ->
|
|
|
- {ok, State}.
|
|
|
+code_change(_Vsn, State, Data, _Extra) ->
|
|
|
+ {ok, State, Data}.
|