refactor(resource): save inflight size into the ETS table
This commit is contained in:
parent
7242ffd713
commit
8307f04c2e
|
@ -132,13 +132,13 @@ init({Id, Index, Opts}) ->
|
||||||
undefined
|
undefined
|
||||||
end,
|
end,
|
||||||
emqx_metrics_worker:inc(?RES_METRICS, Id, 'queuing', queue_count(Queue)),
|
emqx_metrics_worker:inc(?RES_METRICS, Id, 'queuing', queue_count(Queue)),
|
||||||
ok = inflight_new(Name),
|
InfltWinSZ = maps:get(async_inflight_window, Opts, ?DEFAULT_INFLIGHT),
|
||||||
|
ok = inflight_new(Name, InfltWinSZ),
|
||||||
HCItvl = maps:get(health_check_interval, Opts, ?HEALTHCHECK_INTERVAL),
|
HCItvl = maps:get(health_check_interval, Opts, ?HEALTHCHECK_INTERVAL),
|
||||||
St = #{
|
St = #{
|
||||||
id => Id,
|
id => Id,
|
||||||
index => Index,
|
index => Index,
|
||||||
name => Name,
|
name => Name,
|
||||||
async_inflight_window => maps:get(async_inflight_window, Opts, ?DEFAULT_INFLIGHT),
|
|
||||||
enable_batch => maps:get(enable_batch, Opts, false),
|
enable_batch => maps:get(enable_batch, Opts, false),
|
||||||
batch_size => BatchSize,
|
batch_size => BatchSize,
|
||||||
batch_time => maps:get(batch_time, Opts, ?DEFAULT_BATCH_TIME),
|
batch_time => maps:get(batch_time, Opts, ?DEFAULT_BATCH_TIME),
|
||||||
|
@ -288,8 +288,7 @@ query_or_acc(From, Request, #{enable_batch := true, acc := Acc, acc_left := Left
|
||||||
end;
|
end;
|
||||||
query_or_acc(From, Request, #{enable_batch := false, queue := Q, id := Id} = St) ->
|
query_or_acc(From, Request, #{enable_batch := false, queue := Q, id := Id} = St) ->
|
||||||
QueryOpts = #{
|
QueryOpts = #{
|
||||||
inflight_name => maps:get(name, St),
|
inflight_name => maps:get(name, St)
|
||||||
inflight_window => maps:get(async_inflight_window, St)
|
|
||||||
},
|
},
|
||||||
Result = call_query(configured, Id, ?QUERY(From, Request), QueryOpts),
|
Result = call_query(configured, Id, ?QUERY(From, Request), QueryOpts),
|
||||||
case reply_caller(Id, ?REPLY(From, Request, Result)) of
|
case reply_caller(Id, ?REPLY(From, Request, Result)) of
|
||||||
|
@ -312,8 +311,7 @@ flush(
|
||||||
) ->
|
) ->
|
||||||
Batch = lists:reverse(Batch0),
|
Batch = lists:reverse(Batch0),
|
||||||
QueryOpts = #{
|
QueryOpts = #{
|
||||||
inflight_name => maps:get(name, St),
|
inflight_name => maps:get(name, St)
|
||||||
inflight_window => maps:get(async_inflight_window, St)
|
|
||||||
},
|
},
|
||||||
emqx_metrics_worker:inc(?RES_METRICS, Id, 'batching', -length(Batch)),
|
emqx_metrics_worker:inc(?RES_METRICS, Id, 'batching', -length(Batch)),
|
||||||
Result = call_query(configured, Id, Batch, QueryOpts),
|
Result = call_query(configured, Id, Batch, QueryOpts),
|
||||||
|
@ -464,12 +462,10 @@ apply_query_fun(sync, Mod, Id, ?QUERY(_, Request) = _Query, ResSt, _QueryOpts) -
|
||||||
apply_query_fun(async, Mod, Id, ?QUERY(_, Request) = Query, ResSt, QueryOpts) ->
|
apply_query_fun(async, Mod, Id, ?QUERY(_, Request) = Query, ResSt, QueryOpts) ->
|
||||||
?tp(call_query_async, #{id => Id, mod => Mod, query => Query, res_st => ResSt}),
|
?tp(call_query_async, #{id => Id, mod => Mod, query => Query, res_st => ResSt}),
|
||||||
Name = maps:get(inflight_name, QueryOpts, undefined),
|
Name = maps:get(inflight_name, QueryOpts, undefined),
|
||||||
WinSize = maps:get(inflight_window, QueryOpts, undefined),
|
|
||||||
?APPLY_RESOURCE(
|
?APPLY_RESOURCE(
|
||||||
call_query_async,
|
call_query_async,
|
||||||
case inflight_is_full(Name, WinSize) of
|
case inflight_is_full(Name) of
|
||||||
true ->
|
true ->
|
||||||
?tp(warning, inflight_full, #{id => Id, wind_size => WinSize}),
|
|
||||||
{async_return, inflight_full};
|
{async_return, inflight_full};
|
||||||
false ->
|
false ->
|
||||||
ok = emqx_metrics_worker:inc(?RES_METRICS, Id, 'inflight'),
|
ok = emqx_metrics_worker:inc(?RES_METRICS, Id, 'inflight'),
|
||||||
|
@ -489,12 +485,10 @@ apply_query_fun(sync, Mod, Id, [?QUERY(_, _) | _] = Batch, ResSt, _QueryOpts) ->
|
||||||
apply_query_fun(async, Mod, Id, [?QUERY(_, _) | _] = Batch, ResSt, QueryOpts) ->
|
apply_query_fun(async, Mod, Id, [?QUERY(_, _) | _] = Batch, ResSt, QueryOpts) ->
|
||||||
?tp(call_batch_query_async, #{id => Id, mod => Mod, batch => Batch, res_st => ResSt}),
|
?tp(call_batch_query_async, #{id => Id, mod => Mod, batch => Batch, res_st => ResSt}),
|
||||||
Name = maps:get(inflight_name, QueryOpts, undefined),
|
Name = maps:get(inflight_name, QueryOpts, undefined),
|
||||||
WinSize = maps:get(inflight_window, QueryOpts, undefined),
|
|
||||||
?APPLY_RESOURCE(
|
?APPLY_RESOURCE(
|
||||||
call_batch_query_async,
|
call_batch_query_async,
|
||||||
case inflight_is_full(Name, WinSize) of
|
case inflight_is_full(Name) of
|
||||||
true ->
|
true ->
|
||||||
?tp(warning, inflight_full, #{id => Id, wind_size => WinSize}),
|
|
||||||
{async_return, inflight_full};
|
{async_return, inflight_full};
|
||||||
false ->
|
false ->
|
||||||
BatchLen = length(Batch),
|
BatchLen = length(Batch),
|
||||||
|
@ -540,27 +534,32 @@ batch_reply_after_query(Pid, Id, Name, Ref, Batch, Result) ->
|
||||||
end.
|
end.
|
||||||
%%==============================================================================
|
%%==============================================================================
|
||||||
%% the inflight queue for async query
|
%% the inflight queue for async query
|
||||||
|
-define(SIZE_REF, -1).
|
||||||
inflight_new(Name) ->
|
inflight_new(Name, InfltWinSZ) ->
|
||||||
_ = ets:new(Name, [named_table, ordered_set, public, {write_concurrency, true}]),
|
_ = ets:new(Name, [named_table, ordered_set, public, {write_concurrency, true}]),
|
||||||
|
inflight_append(Name, ?SIZE_REF, {size, InfltWinSZ}),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
inflight_get_first(Name) ->
|
inflight_get_first(Name) ->
|
||||||
case ets:first(Name) of
|
case ets:next(Name, ?SIZE_REF) of
|
||||||
'$end_of_table' ->
|
'$end_of_table' ->
|
||||||
empty;
|
empty;
|
||||||
Ref ->
|
Ref ->
|
||||||
case ets:lookup(Name, Ref) of
|
case ets:lookup(Name, Ref) of
|
||||||
[Object] -> Object;
|
[Object] ->
|
||||||
[] -> inflight_get_first(Name)
|
Object;
|
||||||
|
[] ->
|
||||||
|
%% it might have been dropped
|
||||||
|
inflight_get_first(Name)
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
inflight_is_full(undefined, _) ->
|
inflight_is_full(undefined) ->
|
||||||
false;
|
false;
|
||||||
inflight_is_full(Name, MaxSize) ->
|
inflight_is_full(Name) ->
|
||||||
|
[{_, {size, MaxSize}}] = ets:lookup(Name, ?SIZE_REF),
|
||||||
case ets:info(Name, size) of
|
case ets:info(Name, size) of
|
||||||
Size when Size >= MaxSize -> true;
|
Size when Size > MaxSize -> true;
|
||||||
_ -> false
|
_ -> false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,7 @@ t_query_counter_async_query(_) ->
|
||||||
?DEFAULT_RESOURCE_GROUP,
|
?DEFAULT_RESOURCE_GROUP,
|
||||||
?TEST_RESOURCE,
|
?TEST_RESOURCE,
|
||||||
#{name => test_resource, register => true},
|
#{name => test_resource, register => true},
|
||||||
#{query_mode => async}
|
#{query_mode => async, enable_batch => false}
|
||||||
),
|
),
|
||||||
?assertMatch({ok, 0}, emqx_resource:simple_sync_query(?ID, get_counter)),
|
?assertMatch({ok, 0}, emqx_resource:simple_sync_query(?ID, get_counter)),
|
||||||
?check_trace(
|
?check_trace(
|
||||||
|
@ -284,7 +284,7 @@ t_query_counter_async_callback(_) ->
|
||||||
?DEFAULT_RESOURCE_GROUP,
|
?DEFAULT_RESOURCE_GROUP,
|
||||||
?TEST_RESOURCE,
|
?TEST_RESOURCE,
|
||||||
#{name => test_resource, register => true},
|
#{name => test_resource, register => true},
|
||||||
#{query_mode => async, async_inflight_window => 1000000}
|
#{query_mode => async, enable_batch => false, async_inflight_window => 1000000}
|
||||||
),
|
),
|
||||||
?assertMatch({ok, 0}, emqx_resource:simple_sync_query(?ID, get_counter)),
|
?assertMatch({ok, 0}, emqx_resource:simple_sync_query(?ID, get_counter)),
|
||||||
?check_trace(
|
?check_trace(
|
||||||
|
@ -338,6 +338,7 @@ t_query_counter_async_inflight(_) ->
|
||||||
#{name => test_resource, register => true},
|
#{name => test_resource, register => true},
|
||||||
#{
|
#{
|
||||||
query_mode => async,
|
query_mode => async,
|
||||||
|
enable_batch => false,
|
||||||
async_inflight_window => WindowSize,
|
async_inflight_window => WindowSize,
|
||||||
worker_pool_size => 1,
|
worker_pool_size => 1,
|
||||||
resume_interval => 300
|
resume_interval => 300
|
||||||
|
@ -358,7 +359,7 @@ t_query_counter_async_inflight(_) ->
|
||||||
end
|
end
|
||||||
),
|
),
|
||||||
|
|
||||||
%% this will block the resource_worker
|
%% this will block the resource_worker as the inflight windown is full now
|
||||||
ok = emqx_resource:query(?ID, {inc_counter, 1}),
|
ok = emqx_resource:query(?ID, {inc_counter, 1}),
|
||||||
?assertMatch(0, ets:info(Tab0, size)),
|
?assertMatch(0, ets:info(Tab0, size)),
|
||||||
%% sleep to make the resource_worker resume some times
|
%% sleep to make the resource_worker resume some times
|
||||||
|
@ -683,17 +684,6 @@ inc_counter_in_parallel(N, Opts) ->
|
||||||
|| Pid <- Pids
|
|| Pid <- Pids
|
||||||
].
|
].
|
||||||
|
|
||||||
% verify_inflight_full(WindowSize) ->
|
|
||||||
% ?check_trace(
|
|
||||||
% ?TRACE_OPTS,
|
|
||||||
% emqx_resource:query(?ID, {inc_counter, 1}),
|
|
||||||
% fun(Return, Trace) ->
|
|
||||||
% QueryTrace = ?of_kind(inflight_full, Trace),
|
|
||||||
% ?assertMatch([#{wind_size := WindowSize} | _], QueryTrace),
|
|
||||||
% ?assertMatch(ok, Return)
|
|
||||||
% end
|
|
||||||
% ).
|
|
||||||
|
|
||||||
bin_config() ->
|
bin_config() ->
|
||||||
<<"\"name\": \"test_resource\"">>.
|
<<"\"name\": \"test_resource\"">>.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue