diff --git a/apps/emqx_rule_engine/src/emqx_rule_index.erl b/apps/emqx_rule_engine/src/emqx_rule_index.erl index 7a3159f9a..70564f62c 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_index.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_index.erl @@ -89,9 +89,13 @@ matches(Topic, Tab, Opts) -> [] -> [] end, Matches = matches(Words, RPrefix, AccIn, Tab), + %% return rules ordered by Rule ID case Matches of - #{} -> maps:values(Matches); - _ -> Matches + #{} -> + maps:values(Matches); + _ -> + F = fun({_, {ID1}}, {_, {ID2}}) -> ID1 < ID2 end, + lists:sort(F, Matches) end. matches(Words, RPrefix, Acc, Tab) -> diff --git a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl index c8bebab99..87563f660 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl @@ -58,6 +58,7 @@ groups() -> t_create_existing_rule, t_get_rules_for_topic, t_get_rules_for_topic_2, + t_get_rules_for_topic_3, t_get_rules_with_same_event, t_get_rule_ids_by_action, t_ensure_action_removed @@ -399,6 +400,45 @@ t_get_rules_for_topic_2(_Config) -> ]), ok. +t_get_rules_for_topic_3(_Config) -> + ok = create_rules( + [ + make_simple_rule(<<"rule-debug-5">>, <<"select * from \"simple/#\"">>), + make_simple_rule(<<"rule-debug-4">>, <<"select * from \"simple/+\"">>), + make_simple_rule(<<"rule-debug-3">>, <<"select * from \"simple/+/1\"">>), + make_simple_rule(<<"rule-debug-2">>, <<"select * from \"simple/1\"">>), + make_simple_rule( + <<"rule-debug-1">>, + <<"select * from \"simple/2\", \"simple/+\", \"simple/3\"">> + ) + ] + ), + Rules1 = get_rules_for_topic_in_e510_impl(<<"simple/1">>), + Rules2 = emqx_rule_engine:get_rules_for_topic(<<"simple/1">>), + %% assert, ensure the order of rules is the same as e5.1.0 + ?assertEqual(Rules1, Rules2), + ?assertEqual( + [<<"rule-debug-1">>, <<"rule-debug-2">>, <<"rule-debug-4">>, <<"rule-debug-5">>], + [Id || #{id := Id} <- Rules1] + ), + + ok = delete_rules_by_ids([ + <<"rule-debug-1">>, + <<"rule-debug-2">>, + <<"rule-debug-3">>, + <<"rule-debug-4">>, + <<"rule-debug-5">>, + <<"rule-debug-6">> + ]), + ok. + +get_rules_for_topic_in_e510_impl(Topic) -> + [ + Rule + || Rule = #{from := From} <- emqx_rule_engine:get_rules(), + emqx_topic:match_any(Topic, From) + ]. + t_get_rules_with_same_event(_Config) -> PubT = <<"simple/1">>, PubN = length(emqx_rule_engine:get_rules_with_same_event(PubT)), diff --git a/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl index 42f3f1da0..76ad1cda6 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl @@ -152,6 +152,16 @@ t_match_unique(_) -> [id(M) || M <- emqx_rule_index:matches(<<"a/b/c">>, Tab, [unique])] ). +t_match_ordering(_) -> + Tab = new(), + emqx_rule_index:insert(<<"a/b/+">>, t_match_id2, <<>>, Tab), + emqx_rule_index:insert(<<"a/b/c">>, t_match_id1, <<>>, Tab), + emqx_rule_index:insert(<<"a/b/#">>, t_match_id3, <<>>, Tab), + Ids1 = [id(M) || M <- emqx_rule_index:matches(<<"a/b/c">>, Tab, [])], + Ids2 = [id(M) || M <- emqx_rule_index:matches(<<"a/b/c">>, Tab, [unique])], + ?assertEqual(Ids1, Ids2), + ?assertEqual([t_match_id1, t_match_id2, t_match_id3], Ids1). + new() -> ets:new(?MODULE, [public, ordered_set, {write_concurrency, true}]).