|
|
@@ -94,9 +94,6 @@ basic_apply_rule_test_helper(Config, TraceType, StopAfterRender) ->
|
|
|
%% ===================================
|
|
|
%% Create trace for RuleId
|
|
|
%% ===================================
|
|
|
- Now = erlang:system_time(second) - 10,
|
|
|
- Start = Now,
|
|
|
- End = Now + 60,
|
|
|
TraceName = atom_to_binary(?FUNCTION_NAME),
|
|
|
TraceValue =
|
|
|
case TraceType of
|
|
|
@@ -105,16 +102,7 @@ basic_apply_rule_test_helper(Config, TraceType, StopAfterRender) ->
|
|
|
clientid ->
|
|
|
ClientId
|
|
|
end,
|
|
|
- Trace = #{
|
|
|
- name => TraceName,
|
|
|
- type => TraceType,
|
|
|
- TraceType => TraceValue,
|
|
|
- start_at => Start,
|
|
|
- end_at => End
|
|
|
- },
|
|
|
- emqx_trace_SUITE:reload(),
|
|
|
- ok = emqx_trace:clear(),
|
|
|
- {ok, _} = emqx_trace:create(Trace),
|
|
|
+ create_trace(TraceName, TraceType, TraceValue),
|
|
|
%% ===================================
|
|
|
Context = #{
|
|
|
clientid => ClientId,
|
|
|
@@ -125,13 +113,12 @@ basic_apply_rule_test_helper(Config, TraceType, StopAfterRender) ->
|
|
|
username => <<"u_emqx">>
|
|
|
},
|
|
|
Params = #{
|
|
|
- % body => #{
|
|
|
<<"context">> => Context,
|
|
|
<<"stop_action_after_template_rendering">> => StopAfterRender
|
|
|
- % }
|
|
|
},
|
|
|
emqx_trace:check(),
|
|
|
ok = emqx_trace_handler_SUITE:filesync(TraceName, TraceType),
|
|
|
+ Now = erlang:system_time(second) - 10,
|
|
|
{ok, _} = file:read_file(emqx_trace:log_file(TraceName, Now)),
|
|
|
?assertMatch({ok, _}, call_apply_rule_api(RuleId, Params)),
|
|
|
?retry(
|
|
|
@@ -173,14 +160,175 @@ basic_apply_rule_test_helper(Config, TraceType, StopAfterRender) ->
|
|
|
emqx_trace:delete(TraceName),
|
|
|
ok.
|
|
|
|
|
|
+create_trace(TraceName, TraceType, TraceValue) ->
|
|
|
+ Now = erlang:system_time(second) - 10,
|
|
|
+ Start = Now,
|
|
|
+ End = Now + 60,
|
|
|
+ Trace = #{
|
|
|
+ name => TraceName,
|
|
|
+ type => TraceType,
|
|
|
+ TraceType => TraceValue,
|
|
|
+ start_at => Start,
|
|
|
+ end_at => End
|
|
|
+ },
|
|
|
+ emqx_trace_SUITE:reload(),
|
|
|
+ ok = emqx_trace:clear(),
|
|
|
+ {ok, _} = emqx_trace:create(Trace).
|
|
|
+
|
|
|
+t_apply_rule_test_batch_separation_stop_after_render(_Config) ->
|
|
|
+ MeckOpts = [passthrough, no_link, no_history, non_strict],
|
|
|
+ catch meck:new(emqx_connector_info, MeckOpts),
|
|
|
+ meck:expect(
|
|
|
+ emqx_connector_info,
|
|
|
+ hard_coded_test_connector_info_modules,
|
|
|
+ 0,
|
|
|
+ [emqx_rule_engine_test_connector_info]
|
|
|
+ ),
|
|
|
+ emqx_connector_info:clean_cache(),
|
|
|
+ catch meck:new(emqx_action_info, MeckOpts),
|
|
|
+ meck:expect(
|
|
|
+ emqx_action_info,
|
|
|
+ hard_coded_test_action_info_modules,
|
|
|
+ 0,
|
|
|
+ [emqx_rule_engine_test_action_info]
|
|
|
+ ),
|
|
|
+ emqx_action_info:clean_cache(),
|
|
|
+ {ok, _} = emqx_connector:create(rule_engine_test, ?FUNCTION_NAME, #{}),
|
|
|
+ Name = atom_to_binary(?FUNCTION_NAME),
|
|
|
+ ActionConf =
|
|
|
+ #{
|
|
|
+ <<"connector">> => Name,
|
|
|
+ <<"parameters">> =>
|
|
|
+ #{
|
|
|
+ <<"values">> =>
|
|
|
+ #{
|
|
|
+ <<"send_to_pid">> => emqx_utils:bin_to_hexstr(
|
|
|
+ term_to_binary(self()), upper
|
|
|
+ )
|
|
|
+ }
|
|
|
+ },
|
|
|
+ <<"resource_opts">> => #{
|
|
|
+ <<"batch_size">> => 1000,
|
|
|
+ <<"batch_time">> => 500
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {ok, _} = emqx_bridge_v2:create(
|
|
|
+ rule_engine_test,
|
|
|
+ ?FUNCTION_NAME,
|
|
|
+ ActionConf
|
|
|
+ ),
|
|
|
+ SQL = <<"SELECT payload.is_stop_after_render as stop_after_render FROM \"", Name/binary, "\"">>,
|
|
|
+ {ok, RuleID} = create_rule_with_action(
|
|
|
+ rule_engine_test,
|
|
|
+ ?FUNCTION_NAME,
|
|
|
+ SQL
|
|
|
+ ),
|
|
|
+ create_trace(Name, ruleid, RuleID),
|
|
|
+ emqx_trace:check(),
|
|
|
+ ok = emqx_trace_handler_SUITE:filesync(Name, ruleid),
|
|
|
+ Now = erlang:system_time(second) - 10,
|
|
|
+ %% Stop
|
|
|
+ ParmsStopAfterRender = apply_rule_parms(true, Name),
|
|
|
+ ParmsNoStopAfterRender = apply_rule_parms(false, Name),
|
|
|
+ %% Check that batching is working
|
|
|
+ Count = 400,
|
|
|
+ CountMsgFun =
|
|
|
+ fun
|
|
|
+ CountMsgFunRec(0 = _CurCount, GotBatchWithAtLeastTwo) ->
|
|
|
+ GotBatchWithAtLeastTwo;
|
|
|
+ CountMsgFunRec(CurCount, GotBatchWithAtLeastTwo) ->
|
|
|
+ receive
|
|
|
+ List ->
|
|
|
+ Len = length(List),
|
|
|
+ CountMsgFunRec(CurCount - Len, GotBatchWithAtLeastTwo orelse (Len > 1))
|
|
|
+ end
|
|
|
+ end,
|
|
|
+ lists:foreach(
|
|
|
+ fun(_) ->
|
|
|
+ {ok, _} = call_apply_rule_api(RuleID, ParmsStopAfterRender)
|
|
|
+ end,
|
|
|
+ lists:seq(1, Count)
|
|
|
+ ),
|
|
|
+ %% We should get the messages and at least one batch with more than 1
|
|
|
+ true = CountMsgFun(Count, false),
|
|
|
+ %% We should check that we don't get any mixed batch
|
|
|
+ CheckBatchesFun =
|
|
|
+ fun
|
|
|
+ CheckBatchesFunRec(0 = _CurCount) ->
|
|
|
+ ok;
|
|
|
+ CheckBatchesFunRec(CurCount) ->
|
|
|
+ receive
|
|
|
+ [{_, #{<<"stop_after_render">> := StopValue}} | _] = List ->
|
|
|
+ [
|
|
|
+ ?assertMatch(#{<<"stop_after_render">> := StopValue}, Msg)
|
|
|
+ || {_, Msg} <- List
|
|
|
+ ],
|
|
|
+ Len = length(List),
|
|
|
+ CheckBatchesFunRec(CurCount - Len)
|
|
|
+ end
|
|
|
+ end,
|
|
|
+ lists:foreach(
|
|
|
+ fun(_) ->
|
|
|
+ case rand:normal() < 0 of
|
|
|
+ true ->
|
|
|
+ {ok, _} = call_apply_rule_api(RuleID, ParmsStopAfterRender);
|
|
|
+ false ->
|
|
|
+ {ok, _} = call_apply_rule_api(RuleID, ParmsNoStopAfterRender)
|
|
|
+ end
|
|
|
+ end,
|
|
|
+ lists:seq(1, Count)
|
|
|
+ ),
|
|
|
+ CheckBatchesFun(Count),
|
|
|
+ %% Just check that the log file is created as expected
|
|
|
+ ?retry(
|
|
|
+ _Interval0 = 200,
|
|
|
+ _NAttempts0 = 20,
|
|
|
+ begin
|
|
|
+ Bin = read_rule_trace_file(Name, ruleid, Now),
|
|
|
+ ?assertNotEqual(nomatch, binary:match(Bin, [<<"action_success">>]))
|
|
|
+ end
|
|
|
+ ),
|
|
|
+ ok.
|
|
|
+
|
|
|
+apply_rule_parms(StopAfterRender, Name) ->
|
|
|
+ Payload = #{<<"is_stop_after_render">> => StopAfterRender},
|
|
|
+ Context = #{
|
|
|
+ clientid => Name,
|
|
|
+ event_type => message_publish,
|
|
|
+ payload => emqx_utils_json:encode(Payload),
|
|
|
+ qos => 1,
|
|
|
+ topic => Name,
|
|
|
+ username => <<"u_emqx">>
|
|
|
+ },
|
|
|
+ #{
|
|
|
+ <<"context">> => Context,
|
|
|
+ <<"stop_action_after_template_rendering">> => StopAfterRender
|
|
|
+ }.
|
|
|
+
|
|
|
+create_rule_with_action(ActionType, ActionName, SQL) ->
|
|
|
+ BridgeId = emqx_bridge_resource:bridge_id(ActionType, ActionName),
|
|
|
+ Params = #{
|
|
|
+ enable => true,
|
|
|
+ sql => SQL,
|
|
|
+ actions => [BridgeId]
|
|
|
+ },
|
|
|
+ Path = emqx_mgmt_api_test_util:api_path(["rules"]),
|
|
|
+ AuthHeader = emqx_mgmt_api_test_util:auth_header_(),
|
|
|
+ ct:pal("rule action params: ~p", [Params]),
|
|
|
+ case emqx_mgmt_api_test_util:request_api(post, Path, "", AuthHeader, Params) of
|
|
|
+ {ok, Res0} ->
|
|
|
+ #{<<"id">> := RuleId} = emqx_utils_json:decode(Res0, [return_maps]),
|
|
|
+ {ok, RuleId};
|
|
|
+ Error ->
|
|
|
+ Error
|
|
|
+ end.
|
|
|
+
|
|
|
%% Helper Functions
|
|
|
|
|
|
call_apply_rule_api(RuleId, Params) ->
|
|
|
Method = post,
|
|
|
Path = emqx_mgmt_api_test_util:api_path(["rules", RuleId, "test"]),
|
|
|
- ct:pal("sql test (http):\n ~p", [Params]),
|
|
|
Res = request(Method, Path, Params),
|
|
|
- ct:pal("sql test (http) result:\n ~p", [Res]),
|
|
|
Res.
|
|
|
|
|
|
request(Method, Path, Params) ->
|