|
|
@@ -42,19 +42,18 @@
|
|
|
]).
|
|
|
|
|
|
-export([
|
|
|
- set_resource_status_connecting/1,
|
|
|
- manager_id_to_resource_id/1
|
|
|
+ set_resource_status_connecting/1
|
|
|
]).
|
|
|
|
|
|
% Server
|
|
|
--export([start_link/6]).
|
|
|
+-export([start_link/5]).
|
|
|
|
|
|
% Behaviour
|
|
|
-export([init/1, callback_mode/0, handle_event/4, terminate/3]).
|
|
|
|
|
|
% State record
|
|
|
-record(data, {
|
|
|
- id, manager_id, group, mod, callback_mode, query_mode, config, opts, status, state, error, pid
|
|
|
+ id, group, mod, callback_mode, query_mode, config, opts, status, state, error, pid
|
|
|
}).
|
|
|
-type data() :: #data{}.
|
|
|
|
|
|
@@ -69,13 +68,6 @@
|
|
|
%% API
|
|
|
%%------------------------------------------------------------------------------
|
|
|
|
|
|
-make_manager_id(ResId) ->
|
|
|
- emqx_resource:generate_id(ResId).
|
|
|
-
|
|
|
-manager_id_to_resource_id(MgrId) ->
|
|
|
- [ResId, _Index] = string:split(MgrId, ":", trailing),
|
|
|
- ResId.
|
|
|
-
|
|
|
%% @doc Called from emqx_resource when starting a resource instance.
|
|
|
%%
|
|
|
%% Triggers the emqx_resource_manager_sup supervisor to actually create
|
|
|
@@ -92,8 +84,7 @@ ensure_resource(ResId, Group, ResourceType, Config, Opts) ->
|
|
|
{ok, _Group, Data} ->
|
|
|
{ok, Data};
|
|
|
{error, not_found} ->
|
|
|
- MgrId = set_new_owner(ResId),
|
|
|
- create_and_return_data(MgrId, ResId, Group, ResourceType, Config, Opts)
|
|
|
+ create_and_return_data(ResId, Group, ResourceType, Config, Opts)
|
|
|
end.
|
|
|
|
|
|
%% @doc Called from emqx_resource when recreating a resource which may or may not exist
|
|
|
@@ -103,23 +94,22 @@ recreate(ResId, ResourceType, NewConfig, Opts) ->
|
|
|
case lookup(ResId) of
|
|
|
{ok, Group, #{mod := ResourceType, status := _} = _Data} ->
|
|
|
_ = remove(ResId, false),
|
|
|
- MgrId = set_new_owner(ResId),
|
|
|
- create_and_return_data(MgrId, ResId, Group, ResourceType, NewConfig, Opts);
|
|
|
+ create_and_return_data(ResId, Group, ResourceType, NewConfig, Opts);
|
|
|
{ok, _, #{mod := Mod}} when Mod =/= ResourceType ->
|
|
|
{error, updating_to_incorrect_resource_type};
|
|
|
{error, not_found} ->
|
|
|
{error, not_found}
|
|
|
end.
|
|
|
|
|
|
-create_and_return_data(MgrId, ResId, Group, ResourceType, Config, Opts) ->
|
|
|
- _ = create(MgrId, ResId, Group, ResourceType, Config, Opts),
|
|
|
+create_and_return_data(ResId, Group, ResourceType, Config, Opts) ->
|
|
|
+ _ = create(ResId, Group, ResourceType, Config, Opts),
|
|
|
{ok, _Group, Data} = lookup(ResId),
|
|
|
{ok, Data}.
|
|
|
|
|
|
%% @doc Create a resource_manager and wait until it is running
|
|
|
-create(MgrId, ResId, Group, ResourceType, Config, Opts) ->
|
|
|
+create(ResId, Group, ResourceType, Config, Opts) ->
|
|
|
% The state machine will make the actual call to the callback/resource module after init
|
|
|
- ok = emqx_resource_manager_sup:ensure_child(MgrId, ResId, Group, ResourceType, Config, Opts),
|
|
|
+ ok = emqx_resource_manager_sup:ensure_child(ResId, Group, ResourceType, Config, Opts),
|
|
|
ok = emqx_metrics_worker:create_metrics(
|
|
|
?RES_METRICS,
|
|
|
ResId,
|
|
|
@@ -164,15 +154,12 @@ create(MgrId, ResId, Group, ResourceType, Config, Opts) ->
|
|
|
ok | {error, Reason :: term()}.
|
|
|
create_dry_run(ResourceType, Config) ->
|
|
|
ResId = make_test_id(),
|
|
|
- MgrId = set_new_owner(ResId),
|
|
|
Opts =
|
|
|
case is_map(Config) of
|
|
|
true -> maps:get(resource_opts, Config, #{});
|
|
|
false -> #{}
|
|
|
end,
|
|
|
- ok = emqx_resource_manager_sup:ensure_child(
|
|
|
- MgrId, ResId, <<"dry_run">>, ResourceType, Config, Opts
|
|
|
- ),
|
|
|
+ ok = emqx_resource_manager_sup:ensure_child(ResId, <<"dry_run">>, ResourceType, Config, Opts),
|
|
|
case wait_for_ready(ResId, 5000) of
|
|
|
ok ->
|
|
|
remove(ResId);
|
|
|
@@ -283,10 +270,9 @@ health_check(ResId) ->
|
|
|
%% Server start/stop callbacks
|
|
|
|
|
|
%% @doc Function called from the supervisor to actually start the server
|
|
|
-start_link(MgrId, ResId, Group, ResourceType, Config, Opts) ->
|
|
|
+start_link(ResId, Group, ResourceType, Config, Opts) ->
|
|
|
Data = #data{
|
|
|
id = ResId,
|
|
|
- manager_id = MgrId,
|
|
|
group = Group,
|
|
|
mod = ResourceType,
|
|
|
callback_mode = emqx_resource:get_callback_mode(ResourceType),
|
|
|
@@ -320,7 +306,7 @@ terminate({shutdown, removed}, _State, _Data) ->
|
|
|
ok;
|
|
|
terminate(_Reason, _State, Data) ->
|
|
|
_ = maybe_stop_resource(Data),
|
|
|
- ok = delete_cache(Data#data.id, Data#data.manager_id),
|
|
|
+ ok = delete_cache(Data#data.id),
|
|
|
ok.
|
|
|
|
|
|
%% Behavior callback
|
|
|
@@ -345,9 +331,6 @@ handle_event({call, From}, start, State, Data) when
|
|
|
start_resource(Data, From);
|
|
|
handle_event({call, From}, start, _State, _Data) ->
|
|
|
{keep_state_and_data, [{reply, From, ok}]};
|
|
|
-% Called when the resource received a `quit` message
|
|
|
-handle_event(info, quit, _State, _Data) ->
|
|
|
- {stop, {shutdown, quit}};
|
|
|
% Called when the resource is to be stopped
|
|
|
handle_event({call, From}, stop, stopped, _Data) ->
|
|
|
{keep_state_and_data, [{reply, From, ok}]};
|
|
|
@@ -429,20 +412,8 @@ log_cache_consistency({_, DataCached}, Data) ->
|
|
|
%%------------------------------------------------------------------------------
|
|
|
%% internal functions
|
|
|
%%------------------------------------------------------------------------------
|
|
|
-insert_cache(ResId, Group, Data = #data{manager_id = MgrId}) ->
|
|
|
- case get_owner(ResId) of
|
|
|
- not_found ->
|
|
|
- ets:insert(?ETS_TABLE, {ResId, Group, Data});
|
|
|
- MgrId ->
|
|
|
- ets:insert(?ETS_TABLE, {ResId, Group, Data});
|
|
|
- _ ->
|
|
|
- ?SLOG(error, #{
|
|
|
- msg => get_resource_owner_failed,
|
|
|
- resource_id => ResId,
|
|
|
- action => quit_resource
|
|
|
- }),
|
|
|
- self() ! quit
|
|
|
- end.
|
|
|
+insert_cache(ResId, Group, Data = #data{}) ->
|
|
|
+ ets:insert(?ETS_TABLE, {ResId, Group, Data}).
|
|
|
|
|
|
read_cache(ResId) ->
|
|
|
case ets:lookup(?ETS_TABLE, ResId) of
|
|
|
@@ -450,37 +421,14 @@ read_cache(ResId) ->
|
|
|
[] -> not_found
|
|
|
end.
|
|
|
|
|
|
-delete_cache(ResId, MgrId) ->
|
|
|
- case get_owner(ResId) of
|
|
|
- MgrIdNow when MgrIdNow == not_found; MgrIdNow == MgrId ->
|
|
|
- do_delete_cache(ResId);
|
|
|
- _ ->
|
|
|
- ok
|
|
|
- end.
|
|
|
-
|
|
|
-do_delete_cache(<<?TEST_ID_PREFIX, _/binary>> = ResId) ->
|
|
|
+delete_cache(<<?TEST_ID_PREFIX, _/binary>> = ResId) ->
|
|
|
true = ets:delete(?ETS_TABLE, {owner, ResId}),
|
|
|
true = ets:delete(?ETS_TABLE, ResId),
|
|
|
ok;
|
|
|
-do_delete_cache(ResId) ->
|
|
|
+delete_cache(ResId) ->
|
|
|
true = ets:delete(?ETS_TABLE, ResId),
|
|
|
ok.
|
|
|
|
|
|
-set_new_owner(ResId) ->
|
|
|
- MgrId = make_manager_id(ResId),
|
|
|
- ok = set_owner(ResId, MgrId),
|
|
|
- MgrId.
|
|
|
-
|
|
|
-set_owner(ResId, MgrId) ->
|
|
|
- ets:insert(?ETS_TABLE, {{owner, ResId}, MgrId}),
|
|
|
- ok.
|
|
|
-
|
|
|
-get_owner(ResId) ->
|
|
|
- case ets:lookup(?ETS_TABLE, {owner, ResId}) of
|
|
|
- [{_, MgrId}] -> MgrId;
|
|
|
- [] -> not_found
|
|
|
- end.
|
|
|
-
|
|
|
retry_actions(Data) ->
|
|
|
case maps:get(auto_restart_interval, Data#data.opts, ?AUTO_RESTART_INTERVAL) of
|
|
|
undefined ->
|
|
|
@@ -494,7 +442,7 @@ health_check_actions(Data) ->
|
|
|
|
|
|
handle_remove_event(From, ClearMetrics, Data) ->
|
|
|
_ = stop_resource(Data),
|
|
|
- ok = delete_cache(Data#data.id, Data#data.manager_id),
|
|
|
+ ok = delete_cache(Data#data.id),
|
|
|
ok = emqx_resource_buffer_worker_sup:stop_workers(Data#data.id, Data#data.opts),
|
|
|
case ClearMetrics of
|
|
|
true -> ok = emqx_metrics_worker:clear_metrics(?RES_METRICS, Data#data.id);
|
|
|
@@ -504,7 +452,7 @@ handle_remove_event(From, ClearMetrics, Data) ->
|
|
|
|
|
|
start_resource(Data, From) ->
|
|
|
%% in case the emqx_resource:call_start/2 hangs, the lookup/1 can read status from the cache
|
|
|
- case emqx_resource:call_start(Data#data.manager_id, Data#data.mod, Data#data.config) of
|
|
|
+ case emqx_resource:call_start(Data#data.id, Data#data.mod, Data#data.config) of
|
|
|
{ok, ResourceState} ->
|
|
|
UpdatedData = Data#data{status = connecting, state = ResourceState},
|
|
|
%% Perform an initial health_check immediately before transitioning into a connected state
|
|
|
@@ -535,7 +483,7 @@ stop_resource(#data{state = ResState, id = ResId} = Data) ->
|
|
|
%% is returned.
|
|
|
case ResState /= undefined of
|
|
|
true ->
|
|
|
- emqx_resource:call_stop(Data#data.manager_id, Data#data.mod, ResState);
|
|
|
+ emqx_resource:call_stop(Data#data.id, Data#data.mod, ResState);
|
|
|
false ->
|
|
|
ok
|
|
|
end,
|
|
|
@@ -589,7 +537,7 @@ with_health_check(#data{state = undefined} = Data, Func) ->
|
|
|
Func(disconnected, Data);
|
|
|
with_health_check(#data{error = PrevError} = Data, Func) ->
|
|
|
ResId = Data#data.id,
|
|
|
- HCRes = emqx_resource:call_health_check(Data#data.manager_id, Data#data.mod, Data#data.state),
|
|
|
+ HCRes = emqx_resource:call_health_check(Data#data.id, Data#data.mod, Data#data.state),
|
|
|
{Status, NewState, Err} = parse_health_check_result(HCRes, Data),
|
|
|
_ = maybe_alarm(Status, ResId, Err, PrevError),
|
|
|
ok = maybe_resume_resource_workers(ResId, Status),
|