fix(rule_engine): reformat some code for dependent rules discovery
This commit is contained in:
parent
07d5c0f9df
commit
9fd43ef882
|
@ -249,40 +249,30 @@ create_resource(#{type := Type, config := Config0} = Params) ->
|
||||||
|
|
||||||
-spec(update_resource(resource_id(), map()) -> ok | {error, Reason :: term()}).
|
-spec(update_resource(resource_id(), map()) -> ok | {error, Reason :: term()}).
|
||||||
update_resource(ResId, NewParams) ->
|
update_resource(ResId, NewParams) ->
|
||||||
try
|
case emqx_rule_registry:find_enabled_rules_depends_on_resource(ResId) of
|
||||||
lists:foreach(fun(#rule{id = RuleId, enabled = Enabled, actions = Actions}) ->
|
[] -> check_and_update_resource(ResId, NewParams);
|
||||||
lists:foreach(
|
Rules ->
|
||||||
fun (#action_instance{args = #{<<"$resource">> := ResId1}})
|
{error, {dependent_rules_exists, [Id || #rule{id = Id} <- Rules]}}
|
||||||
when ResId =:= ResId1, Enabled =:= true ->
|
|
||||||
throw({dependency_exists, RuleId});
|
|
||||||
(_) -> ok
|
|
||||||
end, Actions)
|
|
||||||
end, ets:tab2list(?RULE_TAB)),
|
|
||||||
do_update_resource_check(ResId, NewParams)
|
|
||||||
catch _ : Reason ->
|
|
||||||
{error, Reason}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_update_resource_check(Id, NewParams) ->
|
check_and_update_resource(Id, NewParams) ->
|
||||||
case emqx_rule_registry:find_resource(Id) of
|
case emqx_rule_registry:find_resource(Id) of
|
||||||
{ok, #resource{id = Id,
|
{ok, #resource{id = Id, type = Type, config = OldConfig, description = OldDescr}} ->
|
||||||
type = Type,
|
|
||||||
config = OldConfig,
|
|
||||||
description = OldDescription} = _OldResource} ->
|
|
||||||
try
|
try
|
||||||
Conifg = maps:get(<<"config">>, NewParams, OldConfig),
|
Conifg = maps:get(<<"config">>, NewParams, OldConfig),
|
||||||
Descr = maps:get(<<"description">>, NewParams, OldDescription),
|
Descr = maps:get(<<"description">>, NewParams, OldDescr),
|
||||||
do_update_resource(#{id => Id, config => Conifg, type => Type,
|
do_check_and_update_resource(#{id => Id, config => Conifg, type => Type,
|
||||||
description => Descr}),
|
description => Descr})
|
||||||
ok
|
catch Error:Reason:ST ->
|
||||||
catch _ : Reason ->
|
?LOG(error, "check_and_update_resource failed: ~0p", [{Error, Reason, ST}]),
|
||||||
{error, Reason}
|
{error, Reason}
|
||||||
end;
|
end;
|
||||||
_Other ->
|
_Other ->
|
||||||
{error, not_found}
|
{error, not_found}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_update_resource(#{id := Id, type := Type, description := NewDescription, config := NewConfig}) ->
|
do_check_and_update_resource(#{id := Id, type := Type, description := NewDescription,
|
||||||
|
config := NewConfig}) ->
|
||||||
case emqx_rule_registry:find_resource_type(Type) of
|
case emqx_rule_registry:find_resource_type(Type) of
|
||||||
{ok, #resource_type{on_create = {Module, Create},
|
{ok, #resource_type{on_create = {Module, Create},
|
||||||
params_spec = ParamSpec}} ->
|
params_spec = ParamSpec}} ->
|
||||||
|
@ -296,7 +286,8 @@ do_update_resource(#{id := Id, type := Type, description := NewDescription, conf
|
||||||
config = Config,
|
config = Config,
|
||||||
description = NewDescription,
|
description = NewDescription,
|
||||||
created_at = erlang:system_time(millisecond)
|
created_at = erlang:system_time(millisecond)
|
||||||
});
|
}),
|
||||||
|
ok;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
error({error, Reason})
|
error({error, Reason})
|
||||||
end
|
end
|
||||||
|
|
|
@ -180,6 +180,7 @@
|
||||||
-define(ERR_NO_ACTION(NAME), list_to_binary(io_lib:format("Action ~s Not Found", [(NAME)]))).
|
-define(ERR_NO_ACTION(NAME), list_to_binary(io_lib:format("Action ~s Not Found", [(NAME)]))).
|
||||||
-define(ERR_NO_RESOURCE(RESID), list_to_binary(io_lib:format("Resource ~s Not Found", [(RESID)]))).
|
-define(ERR_NO_RESOURCE(RESID), list_to_binary(io_lib:format("Resource ~s Not Found", [(RESID)]))).
|
||||||
-define(ERR_NO_RESOURCE_TYPE(TYPE), list_to_binary(io_lib:format("Resource Type ~s Not Found", [(TYPE)]))).
|
-define(ERR_NO_RESOURCE_TYPE(TYPE), list_to_binary(io_lib:format("Resource Type ~s Not Found", [(TYPE)]))).
|
||||||
|
-define(ERR_DEP_RULES_EXISTS(RULEIDS), list_to_binary(io_lib:format("Found rules ~0p depends on this resource, disable them first", [(RULEIDS)]))).
|
||||||
-define(ERR_BADARGS(REASON),
|
-define(ERR_BADARGS(REASON),
|
||||||
begin
|
begin
|
||||||
R0 = list_to_binary(io_lib:format("~0p", [REASON])),
|
R0 = list_to_binary(io_lib:format("~0p", [REASON])),
|
||||||
|
@ -342,14 +343,11 @@ update_resource(#{id := Id}, NewParams) ->
|
||||||
ok ->
|
ok ->
|
||||||
return(ok);
|
return(ok);
|
||||||
{error, not_found} ->
|
{error, not_found} ->
|
||||||
?LOG(error, "Resource not found: ~0p", [Id]),
|
|
||||||
return({error, 400, <<"Resource not found:", Id/binary>>});
|
return({error, 400, <<"Resource not found:", Id/binary>>});
|
||||||
{error, {init_resource, _}} ->
|
{error, {init_resource, _}} ->
|
||||||
?LOG(error, "Init resource failure: ~0p", [Id]),
|
|
||||||
return({error, 500, <<"Init resource failure:", Id/binary>>});
|
return({error, 500, <<"Init resource failure:", Id/binary>>});
|
||||||
{error, {dependency_exists, RuleId}} ->
|
{error, {dependent_rules_exists, RuleIds}} ->
|
||||||
?LOG(error, "Dependency exists: ~0p", [RuleId]),
|
return({error, 400, ?ERR_DEP_RULES_EXISTS(RuleIds)});
|
||||||
return({error, 500, <<"Dependency exists:", RuleId/binary>>});
|
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?LOG(error, "Resource update failed: ~0p", [Reason]),
|
?LOG(error, "Resource update failed: ~0p", [Reason]),
|
||||||
return({error, 500, <<"Resource update failed!">>})
|
return({error, 500, <<"Resource update failed!">>})
|
||||||
|
@ -359,6 +357,8 @@ delete_resource(#{id := Id}, _Params) ->
|
||||||
case emqx_rule_engine:delete_resource(Id) of
|
case emqx_rule_engine:delete_resource(Id) of
|
||||||
ok -> return(ok);
|
ok -> return(ok);
|
||||||
{error, not_found} -> return(ok);
|
{error, not_found} -> return(ok);
|
||||||
|
{error, {dependent_rules_exists, RuleIds}} ->
|
||||||
|
return({error, 400, ?ERR_DEP_RULES_EXISTS(RuleIds)});
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
return({error, 400, ?ERR_BADARGS(Reason)})
|
return({error, 400, ?ERR_BADARGS(Reason)})
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -63,6 +63,8 @@
|
||||||
%% Resource Types
|
%% Resource Types
|
||||||
-export([ get_resource_types/0
|
-export([ get_resource_types/0
|
||||||
, find_resource_type/1
|
, find_resource_type/1
|
||||||
|
, find_rules_depends_on_resource/1
|
||||||
|
, find_enabled_rules_depends_on_resource/1
|
||||||
, register_resource_types/1
|
, register_resource_types/1
|
||||||
, unregister_resource_types_of/1
|
, unregister_resource_types_of/1
|
||||||
]).
|
]).
|
||||||
|
@ -368,20 +370,33 @@ remove_resource_params(ResId) ->
|
||||||
|
|
||||||
%% @private
|
%% @private
|
||||||
delete_resource(ResId) ->
|
delete_resource(ResId) ->
|
||||||
lists:foreach(fun(#rule{id = Id, actions = Actions}) ->
|
case find_enabled_rules_depends_on_resource(ResId) of
|
||||||
lists:foreach(
|
[] -> ok;
|
||||||
fun (#action_instance{args = #{<<"$resource">> := ResId1}})
|
Rules ->
|
||||||
when ResId =:= ResId1 ->
|
throw({dependent_rules_exists, [Id || #rule{id = Id} <- Rules]})
|
||||||
throw({dependency_exists, {rule, Id}});
|
end,
|
||||||
(_) -> ok
|
|
||||||
end, Actions)
|
|
||||||
end, get_rules()),
|
|
||||||
mnesia:delete(?RES_TAB, ResId, write).
|
mnesia:delete(?RES_TAB, ResId, write).
|
||||||
|
|
||||||
%% @private
|
%% @private
|
||||||
insert_resource(Resource) ->
|
insert_resource(Resource) ->
|
||||||
mnesia:write(?RES_TAB, Resource, write).
|
mnesia:write(?RES_TAB, Resource, write).
|
||||||
|
|
||||||
|
find_enabled_rules_depends_on_resource(ResId) ->
|
||||||
|
[R || #rule{enabled = true} = R <- find_rules_depends_on_resource(ResId)].
|
||||||
|
|
||||||
|
find_rules_depends_on_resource(ResId) ->
|
||||||
|
lists:foldl(fun(#rule{actions = Actions} = R, Rules) ->
|
||||||
|
case search_action_despends_on_resource(ResId, Actions) of
|
||||||
|
false -> Rules;
|
||||||
|
{value, _} -> [R | Rules]
|
||||||
|
end
|
||||||
|
end, [], get_rules()).
|
||||||
|
|
||||||
|
search_action_despends_on_resource(ResId, Actions) ->
|
||||||
|
lists:search(fun(#action_instance{args = #{<<"$resource">> := ResId0}}) ->
|
||||||
|
ResId0 =:= ResId
|
||||||
|
end, Actions).
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% Resource Type Management
|
%% Resource Type Management
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue