|
|
@@ -26,7 +26,6 @@
|
|
|
-export([ lookup/1
|
|
|
, get_metrics/1
|
|
|
, list_all/0
|
|
|
- , create_local/3
|
|
|
]).
|
|
|
|
|
|
-export([ hash_call/2
|
|
|
@@ -85,15 +84,6 @@ list_all() ->
|
|
|
error:badarg -> []
|
|
|
end.
|
|
|
|
|
|
-
|
|
|
--spec create_local(instance_id(), resource_type(), resource_config()) ->
|
|
|
- {ok, resource_data()} | {error, term()}.
|
|
|
-create_local(InstId, ResourceType, InstConf) ->
|
|
|
- case hash_call(InstId, {create, InstId, ResourceType, InstConf}, 15000) of
|
|
|
- {ok, Data} -> {ok, Data};
|
|
|
- Error -> Error
|
|
|
- end.
|
|
|
-
|
|
|
%%------------------------------------------------------------------------------
|
|
|
%% gen_server callbacks
|
|
|
%%------------------------------------------------------------------------------
|
|
|
@@ -105,8 +95,8 @@ init({Pool, Id}) ->
|
|
|
true = gproc_pool:connect_worker(Pool, {Pool, Id}),
|
|
|
{ok, #state{worker_pool = Pool, worker_id = Id}}.
|
|
|
|
|
|
-handle_call({create, InstId, ResourceType, Config}, _From, State) ->
|
|
|
- {reply, do_create(InstId, ResourceType, Config), State};
|
|
|
+handle_call({create, InstId, ResourceType, Config, Opts}, _From, State) ->
|
|
|
+ {reply, do_create(InstId, ResourceType, Config, Opts), State};
|
|
|
|
|
|
handle_call({create_dry_run, InstId, ResourceType, Config}, _From, State) ->
|
|
|
{reply, do_create_dry_run(InstId, ResourceType, Config), State};
|
|
|
@@ -146,7 +136,7 @@ code_change(_OldVsn, State, _Extra) ->
|
|
|
|
|
|
%% suppress the race condition check, as these functions are protected in gproc workers
|
|
|
-dialyzer({nowarn_function, [do_recreate/4,
|
|
|
- do_create/3,
|
|
|
+ do_create/4,
|
|
|
do_restart/1,
|
|
|
do_stop/1,
|
|
|
do_health_check/1]}).
|
|
|
@@ -156,10 +146,11 @@ do_recreate(InstId, ResourceType, NewConfig, Params) ->
|
|
|
{ok, #{mod := ResourceType, state := ResourceState, config := OldConfig}} ->
|
|
|
Config = emqx_resource:call_config_merge(ResourceType, OldConfig,
|
|
|
NewConfig, Params),
|
|
|
- case do_create_dry_run(InstId, ResourceType, Config) of
|
|
|
+ TestInstId = iolist_to_binary(emqx_misc:gen_id(16)),
|
|
|
+ case do_create_dry_run(TestInstId, ResourceType, Config) of
|
|
|
ok ->
|
|
|
do_remove(ResourceType, InstId, ResourceState),
|
|
|
- do_create(InstId, ResourceType, Config);
|
|
|
+ do_create(InstId, ResourceType, Config, #{force_create => true});
|
|
|
Error ->
|
|
|
Error
|
|
|
end;
|
|
|
@@ -169,21 +160,27 @@ do_recreate(InstId, ResourceType, NewConfig, Params) ->
|
|
|
{error, not_found}
|
|
|
end.
|
|
|
|
|
|
-do_create(InstId, ResourceType, Config) ->
|
|
|
+do_create(InstId, ResourceType, Config, Opts) ->
|
|
|
+ ForceCreate = maps:get(force_create, Opts, false),
|
|
|
case lookup(InstId) of
|
|
|
{ok, _} -> {ok, already_created};
|
|
|
_ ->
|
|
|
+ Res0 = #{id => InstId, mod => ResourceType, config => Config,
|
|
|
+ status => stopped, state => undefined},
|
|
|
case emqx_resource:call_start(InstId, ResourceType, Config) of
|
|
|
{ok, ResourceState} ->
|
|
|
- ets:insert(emqx_resource_instance, {InstId,
|
|
|
- #{mod => ResourceType, config => Config,
|
|
|
- state => ResourceState, status => stopped}}),
|
|
|
- _ = do_health_check(InstId),
|
|
|
ok = emqx_plugin_libs_metrics:create_metrics(resource_metrics, InstId),
|
|
|
+ %% this is the first time we do health check, this will update the
|
|
|
+ %% status and then do ets:insert/2
|
|
|
+ _ = do_health_check(Res0#{state => ResourceState}),
|
|
|
{ok, force_lookup(InstId)};
|
|
|
- {error, Reason} ->
|
|
|
- logger:error("start ~ts resource ~ts failed: ~p",
|
|
|
+ {error, Reason} when ForceCreate == true ->
|
|
|
+ logger:error("start ~ts resource ~ts failed: ~p, "
|
|
|
+ "force_create it as a stopped resource",
|
|
|
[ResourceType, InstId, Reason]),
|
|
|
+ ets:insert(emqx_resource_instance, {InstId, Res0}),
|
|
|
+ {ok, Res0};
|
|
|
+ {error, Reason} when ForceCreate == false ->
|
|
|
{error, Reason}
|
|
|
end
|
|
|
end.
|
|
|
@@ -243,22 +240,24 @@ do_stop(InstId) ->
|
|
|
Error
|
|
|
end.
|
|
|
|
|
|
-do_health_check(InstId) ->
|
|
|
+do_health_check(InstId) when is_binary(InstId) ->
|
|
|
case lookup(InstId) of
|
|
|
- {ok, #{mod := Mod, state := ResourceState0} = Data} ->
|
|
|
- case emqx_resource:call_health_check(InstId, Mod, ResourceState0) of
|
|
|
- {ok, ResourceState1} ->
|
|
|
- ets:insert(emqx_resource_instance,
|
|
|
- {InstId, Data#{status => started, state => ResourceState1}}),
|
|
|
- ok;
|
|
|
- {error, Reason, ResourceState1} ->
|
|
|
- logger:error("health check for ~p failed: ~p", [InstId, Reason]),
|
|
|
- ets:insert(emqx_resource_instance,
|
|
|
- {InstId, Data#{status => stopped, state => ResourceState1}}),
|
|
|
- {error, Reason}
|
|
|
- end;
|
|
|
- Error ->
|
|
|
- Error
|
|
|
+ {ok, Data} -> do_health_check(Data);
|
|
|
+ Error -> Error
|
|
|
+ end;
|
|
|
+do_health_check(#{state := undefined}) ->
|
|
|
+ {error, resource_not_initialized};
|
|
|
+do_health_check(#{id := InstId, mod := Mod, state := ResourceState0} = Data) ->
|
|
|
+ case emqx_resource:call_health_check(InstId, Mod, ResourceState0) of
|
|
|
+ {ok, ResourceState1} ->
|
|
|
+ ets:insert(emqx_resource_instance,
|
|
|
+ {InstId, Data#{status => started, state => ResourceState1}}),
|
|
|
+ ok;
|
|
|
+ {error, Reason, ResourceState1} ->
|
|
|
+ logger:error("health check for ~p failed: ~p", [InstId, Reason]),
|
|
|
+ ets:insert(emqx_resource_instance,
|
|
|
+ {InstId, Data#{status => stopped, state => ResourceState1}}),
|
|
|
+ {error, Reason}
|
|
|
end.
|
|
|
|
|
|
%%------------------------------------------------------------------------------
|