fix(limiter): fix rate parser, support this format: xMB/s

This commit is contained in:
firest 2022-05-05 15:38:04 +08:00
parent f2e7563b0c
commit acb78d53eb
2 changed files with 29 additions and 11 deletions

View File

@ -199,18 +199,36 @@ ref(Field) -> hoconsc:ref(?MODULE, Field).
to_burst_rate(Str) -> to_burst_rate(Str) ->
to_rate(Str, false, true). to_rate(Str, false, true).
%% rate can be: 10 10MB 10MB/s 10MB/2s infinity
%% e.g. the bytes_in regex tree is:
%%
%% __ infinity
%% | - xMB
%% rate -| |
%% __ ?Size(/?Time) -| - xMB/s
%% | |
%% - xMB/?Time -|
%% - xMB/ys
to_rate(Str, CanInfinity, CanZero) -> to_rate(Str, CanInfinity, CanZero) ->
Tokens = [string:trim(T) || T <- string:tokens(Str, "/")], Regex = "^\s*(?:([0-9]+[a-zA-Z]*)(?:/([0-9]*)([m s h d M S H D]{1,2}))?\s*$)|infinity\s*$",
case Tokens of {ok, MP} = re:compile(Regex),
["infinity"] when CanInfinity -> case re:run(Str, MP, [{capture, all_but_first, list}]) of
{match, []} when CanInfinity ->
{ok, infinity}; {ok, infinity};
%% if time unit is 1s, it can be omitted %% if time unit is 1s, it can be omitted
[QuotaStr] -> {match, [QuotaStr]} ->
Fun = fun(Quota) -> Fun = fun(Quota) ->
{ok, Quota * minimum_period() / ?UNIT_TIME_IN_MS} {ok, Quota * minimum_period() / ?UNIT_TIME_IN_MS}
end, end,
to_capacity(QuotaStr, Str, CanZero, Fun); to_capacity(QuotaStr, Str, CanZero, Fun);
[QuotaStr, Interval] -> {match, [QuotaStr, TimeVal, TimeUnit]} ->
Interval =
case TimeVal of
%% for xM/s
[] -> "1" ++ TimeUnit;
%% for xM/ys
_ -> TimeVal ++ TimeUnit
end,
Fun = fun(Quota) -> Fun = fun(Quota) ->
try try
case emqx_schema:to_duration_ms(Interval) of case emqx_schema:to_duration_ms(Interval) of
@ -246,11 +264,11 @@ check_capacity(_Str, Quota, _CanZero, Cont) ->
Cont(Quota). Cont(Quota).
to_capacity(Str) -> to_capacity(Str) ->
Regex = "^\s*(?:([0-9]+)([a-zA-z]*))|infinity\s*$", Regex = "^\s*(?:([0-9]+)([a-zA-Z]*))|infinity\s*$",
to_quota(Str, Regex). to_quota(Str, Regex).
to_initial(Str) -> to_initial(Str) ->
Regex = "^\s*([0-9]+)([a-zA-z]*)\s*$", Regex = "^\s*([0-9]+)([a-zA-Z]*)\s*$",
to_quota(Str, Regex). to_quota(Str, Regex).
to_quota(Str, Regex) -> to_quota(Str, Regex) ->

View File

@ -667,16 +667,16 @@ typename_to_spec("log_level()", _Mod) ->
enum => [debug, info, notice, warning, error, critical, alert, emergency, all] enum => [debug, info, notice, warning, error, critical, alert, emergency, all]
}; };
typename_to_spec("rate()", _Mod) -> typename_to_spec("rate()", _Mod) ->
#{type => string, example => <<"10M/s">>}; #{type => string, example => <<"10MB">>};
typename_to_spec("capacity()", _Mod) -> typename_to_spec("capacity()", _Mod) ->
#{type => string, example => <<"100M">>}; #{type => string, example => <<"100MB">>};
typename_to_spec("burst_rate()", _Mod) -> typename_to_spec("burst_rate()", _Mod) ->
%% 0/0s = no burst %% 0/0s = no burst
#{type => string, example => <<"10M/1s">>}; #{type => string, example => <<"10MB">>};
typename_to_spec("failure_strategy()", _Mod) -> typename_to_spec("failure_strategy()", _Mod) ->
#{type => string, example => <<"force">>}; #{type => string, example => <<"force">>};
typename_to_spec("initial()", _Mod) -> typename_to_spec("initial()", _Mod) ->
#{type => string, example => <<"0M">>}; #{type => string, example => <<"0MB">>};
typename_to_spec("bucket_name()", _Mod) -> typename_to_spec("bucket_name()", _Mod) ->
#{type => string, example => <<"retainer">>}; #{type => string, example => <<"retainer">>};
typename_to_spec(Name, Mod) -> typename_to_spec(Name, Mod) ->