refactor(resource): support async create mode
This commit is contained in:
parent
2277b75b2f
commit
e1ab331a30
|
@ -979,7 +979,7 @@ authenticator_examples() ->
|
||||||
mechanism => <<"password-based">>,
|
mechanism => <<"password-based">>,
|
||||||
backend => <<"http">>,
|
backend => <<"http">>,
|
||||||
method => <<"post">>,
|
method => <<"post">>,
|
||||||
url => <<"http://127.0.0.2:8080">>,
|
url => <<"http://127.0.0.1:18083">>,
|
||||||
headers => #{
|
headers => #{
|
||||||
<<"content-type">> => <<"application/json">>
|
<<"content-type">> => <<"application/json">>
|
||||||
},
|
},
|
||||||
|
|
|
@ -218,7 +218,7 @@ create(Type, Name, Conf) ->
|
||||||
?SLOG(info, #{msg => "create bridge", type => Type, name => Name,
|
?SLOG(info, #{msg => "create bridge", type => Type, name => Name,
|
||||||
config => Conf}),
|
config => Conf}),
|
||||||
case emqx_resource:create_local(resource_id(Type, Name), emqx_bridge:resource_type(Type),
|
case emqx_resource:create_local(resource_id(Type, Name), emqx_bridge:resource_type(Type),
|
||||||
parse_confs(Type, Name, Conf), #{force_create => true}) of
|
parse_confs(Type, Name, Conf), #{async_create => true}) of
|
||||||
{ok, already_created} -> maybe_disable_bridge(Type, Name, Conf);
|
{ok, already_created} -> maybe_disable_bridge(Type, Name, Conf);
|
||||||
{ok, _} -> maybe_disable_bridge(Type, Name, Conf);
|
{ok, _} -> maybe_disable_bridge(Type, Name, Conf);
|
||||||
{error, Reason} -> {error, Reason}
|
{error, Reason} -> {error, Reason}
|
||||||
|
@ -263,7 +263,8 @@ recreate(Type, Name) ->
|
||||||
|
|
||||||
recreate(Type, Name, Conf) ->
|
recreate(Type, Name, Conf) ->
|
||||||
emqx_resource:recreate_local(resource_id(Type, Name),
|
emqx_resource:recreate_local(resource_id(Type, Name),
|
||||||
emqx_bridge:resource_type(Type), parse_confs(Type, Name, Conf), []).
|
emqx_bridge:resource_type(Type), parse_confs(Type, Name, Conf),
|
||||||
|
#{async_create => true}).
|
||||||
|
|
||||||
create_dry_run(Type, Conf) ->
|
create_dry_run(Type, Conf) ->
|
||||||
Conf0 = Conf#{<<"ingress">> => #{<<"remote_topic">> => <<"t">>}},
|
Conf0 = Conf#{<<"ingress">> => #{<<"remote_topic">> => <<"t">>}},
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
%% The emqx_resource:create/4 will return OK event if the Mod:on_start/2 fails,
|
%% The emqx_resource:create/4 will return OK event if the Mod:on_start/2 fails,
|
||||||
%% the 'status' of the resource will be 'stopped' in this case.
|
%% the 'status' of the resource will be 'stopped' in this case.
|
||||||
%% Defaults to 'false'
|
%% Defaults to 'false'
|
||||||
force_create => boolean()
|
async_create => boolean()
|
||||||
}.
|
}.
|
||||||
-type after_query() :: {[OnSuccess :: after_query_fun()], [OnFailed :: after_query_fun()]} |
|
-type after_query() :: {[OnSuccess :: after_query_fun()], [OnFailed :: after_query_fun()]} |
|
||||||
undefined.
|
undefined.
|
||||||
|
|
|
@ -148,14 +148,19 @@ code_change(_OldVsn, State, _Extra) ->
|
||||||
|
|
||||||
do_recreate(InstId, ResourceType, NewConfig, Opts) ->
|
do_recreate(InstId, ResourceType, NewConfig, Opts) ->
|
||||||
case lookup(InstId) of
|
case lookup(InstId) of
|
||||||
{ok, #{mod := ResourceType} = Data} ->
|
{ok, #{mod := ResourceType, status := started} = Data} ->
|
||||||
|
%% If this resource is in use (status='started'), we should make sure
|
||||||
|
%% the new config is OK before removing the old one.
|
||||||
case do_create_dry_run(ResourceType, NewConfig) of
|
case do_create_dry_run(ResourceType, NewConfig) of
|
||||||
ok ->
|
ok ->
|
||||||
do_remove(Data, false),
|
do_remove(Data, false),
|
||||||
do_create(InstId, ResourceType, NewConfig, Opts#{force_create => true});
|
do_create(InstId, ResourceType, NewConfig, Opts);
|
||||||
Error ->
|
Error ->
|
||||||
Error
|
Error
|
||||||
end;
|
end;
|
||||||
|
{ok, #{mod := ResourceType, status := _} = Data} ->
|
||||||
|
do_remove(Data, false),
|
||||||
|
do_create(InstId, ResourceType, NewConfig, Opts);
|
||||||
{ok, #{mod := Mod}} when Mod =/= ResourceType ->
|
{ok, #{mod := Mod}} when Mod =/= ResourceType ->
|
||||||
{error, updating_to_incorrect_resource_type};
|
{error, updating_to_incorrect_resource_type};
|
||||||
{error, not_found} ->
|
{error, not_found} ->
|
||||||
|
@ -164,21 +169,21 @@ do_recreate(InstId, ResourceType, NewConfig, Opts) ->
|
||||||
|
|
||||||
do_create(InstId, ResourceType, Config, Opts) ->
|
do_create(InstId, ResourceType, Config, Opts) ->
|
||||||
case lookup(InstId) of
|
case lookup(InstId) of
|
||||||
{ok, _} -> {ok, already_created};
|
{ok, _} ->
|
||||||
|
{ok, already_created};
|
||||||
{error, not_found} ->
|
{error, not_found} ->
|
||||||
case do_start(InstId, ResourceType, Config, Opts) of
|
case do_start(InstId, ResourceType, Config, Opts) of
|
||||||
ok ->
|
ok ->
|
||||||
ok = emqx_resource_health_check_sup:create_checker(InstId,
|
|
||||||
maps:get(health_check_interval, Opts, 15000)),
|
|
||||||
ok = emqx_plugin_libs_metrics:clear_metrics(resource_metrics, InstId),
|
ok = emqx_plugin_libs_metrics:clear_metrics(resource_metrics, InstId),
|
||||||
{ok, force_lookup(InstId)};
|
{ok, force_lookup(InstId)};
|
||||||
Error -> Error
|
Error ->
|
||||||
|
Error
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_create_dry_run(ResourceType, Config) ->
|
do_create_dry_run(ResourceType, Config) ->
|
||||||
InstId = make_test_id(),
|
InstId = make_test_id(),
|
||||||
Opts = #{force_create => false},
|
Opts = #{async_create => false},
|
||||||
case do_create(InstId, ResourceType, Config, Opts) of
|
case do_create(InstId, ResourceType, Config, Opts) of
|
||||||
{ok, Data} ->
|
{ok, Data} ->
|
||||||
Return = do_health_check(Data),
|
Return = do_health_check(Data),
|
||||||
|
@ -200,7 +205,6 @@ do_remove(#{id := InstId} = Data, ClearMetrics) ->
|
||||||
true -> ok = emqx_plugin_libs_metrics:clear_metrics(resource_metrics, InstId);
|
true -> ok = emqx_plugin_libs_metrics:clear_metrics(resource_metrics, InstId);
|
||||||
false -> ok
|
false -> ok
|
||||||
end,
|
end,
|
||||||
_ = emqx_resource_health_check_sup:delete_checker(InstId),
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
do_restart(InstId, Opts) ->
|
do_restart(InstId, Opts) ->
|
||||||
|
@ -213,24 +217,32 @@ do_restart(InstId, Opts) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_start(InstId, ResourceType, Config, Opts) when is_binary(InstId) ->
|
do_start(InstId, ResourceType, Config, Opts) when is_binary(InstId) ->
|
||||||
ForceCreate = maps:get(force_create, Opts, false),
|
InitData = #{id => InstId, mod => ResourceType, config => Config,
|
||||||
Res0 = #{id => InstId, mod => ResourceType, config => Config,
|
|
||||||
status => starting, state => undefined},
|
status => starting, state => undefined},
|
||||||
%% The `emqx_resource:call_start/3` need the instance exist beforehand
|
%% The `emqx_resource:call_start/3` need the instance exist beforehand
|
||||||
ets:insert(emqx_resource_instance, {InstId, Res0}),
|
ets:insert(emqx_resource_instance, {InstId, InitData}),
|
||||||
|
case maps:get(async_create, Opts, false) of
|
||||||
|
false ->
|
||||||
|
start_and_check(InstId, ResourceType, Config, Opts, InitData);
|
||||||
|
true ->
|
||||||
|
spawn(fun() ->
|
||||||
|
start_and_check(InstId, ResourceType, Config, Opts, InitData)
|
||||||
|
end),
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
start_and_check(InstId, ResourceType, Config, Opts, Data) ->
|
||||||
case emqx_resource:call_start(InstId, ResourceType, Config) of
|
case emqx_resource:call_start(InstId, ResourceType, Config) of
|
||||||
{ok, ResourceState} ->
|
{ok, ResourceState} ->
|
||||||
%% this is the first time we do health check, this will update the
|
Data2 = Data#{state => ResourceState},
|
||||||
%% status and then do ets:insert/2
|
ets:insert(emqx_resource_instance, {InstId, Data2}),
|
||||||
_ = do_health_check(Res0#{state => ResourceState}),
|
case maps:get(async_create, Opts, false) of
|
||||||
ok;
|
false -> do_health_check(Data2);
|
||||||
{error, Reason} when ForceCreate == true ->
|
true -> emqx_resource_health_check_sup:create_checker(InstId,
|
||||||
logger:warning("start ~ts resource ~ts failed: ~p, force_create it",
|
maps:get(health_check_interval, Opts, 15000))
|
||||||
[ResourceType, InstId, Reason]),
|
end;
|
||||||
ets:insert(emqx_resource_instance, {InstId, Res0}),
|
{error, Reason} ->
|
||||||
ok;
|
ets:insert(emqx_resource_instance, {InstId, Data#{status => stopped}}),
|
||||||
{error, Reason} when ForceCreate == false ->
|
|
||||||
ets:delete(emqx_resource_instance, InstId),
|
|
||||||
{error, Reason}
|
{error, Reason}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -240,14 +252,12 @@ do_stop(#{state := undefined}) ->
|
||||||
ok;
|
ok;
|
||||||
do_stop(#{id := InstId, mod := Mod, state := ResourceState} = Data) ->
|
do_stop(#{id := InstId, mod := Mod, state := ResourceState} = Data) ->
|
||||||
_ = emqx_resource:call_stop(InstId, Mod, ResourceState),
|
_ = emqx_resource:call_stop(InstId, Mod, ResourceState),
|
||||||
|
ok = emqx_resource_health_check_sup:delete_checker(InstId),
|
||||||
ets:insert(emqx_resource_instance, {InstId, Data#{status => stopped}}),
|
ets:insert(emqx_resource_instance, {InstId, Data#{status => stopped}}),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
do_health_check(InstId) when is_binary(InstId) ->
|
do_health_check(InstId) when is_binary(InstId) ->
|
||||||
case lookup(InstId) of
|
do_with_instance_data(InstId, fun do_health_check/1, []);
|
||||||
{ok, Data} -> do_health_check(Data);
|
|
||||||
Error -> Error
|
|
||||||
end;
|
|
||||||
do_health_check(#{state := undefined}) ->
|
do_health_check(#{state := undefined}) ->
|
||||||
{error, resource_not_initialized};
|
{error, resource_not_initialized};
|
||||||
do_health_check(#{id := InstId, mod := Mod, state := ResourceState0} = Data) ->
|
do_health_check(#{id := InstId, mod := Mod, state := ResourceState0} = Data) ->
|
||||||
|
|
Loading…
Reference in New Issue