./ct_report/coverage/shaper.COVER.html

1 %%==============================================================================
2 %% Copyright 2016 Erlang Solutions Ltd.
3 %%
4 %% Licensed under the Apache License, Version 2.0 (the "License");
5 %% you may not use this file except in compliance with the License.
6 %% You may obtain a copy of the License at
7 %%
8 %% http://www.apache.org/licenses/LICENSE-2.0
9 %%
10 %% Unless required by applicable law or agreed to in writing, software
11 %% distributed under the License is distributed on an "AS IS" BASIS,
12 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 %% See the License for the specific language governing permissions and
14 %% limitations under the License.
15 %%==============================================================================
16
17 -module(shaper).
18 -author('konrad.zemek@erlang-solutions.com').
19
20 -export([new/1, update/2]).
21
22 -record(shaper, {
23 max_rate :: undefined | pos_integer(),
24 tokens = 0 :: non_neg_integer(),
25 last_update = erlang:monotonic_time(millisecond) :: integer()
26 }).
27
28 -type shaper() :: #shaper{} | none.
29
30 -export_type([shaper/0]).
31
32 -spec new(atom()) -> shaper().
33 new(Name) ->
34 15072 case mongoose_config:lookup_opt([shaper, Name]) of
35 {ok, #{max_rate := MaxRatePerSecond}} ->
36 9136 #shaper{max_rate = MaxRatePerSecond,
37 tokens = MaxRatePerSecond,
38 last_update = erlang:monotonic_time(millisecond)};
39 5936 {error, not_found} -> none
40 end.
41
42 %% @doc Update shaper.
43 %% `Delay' is how many milliseconds to wait.
44 -spec update(shaper(), Size :: pos_integer()) -> {shaper(), Delay :: non_neg_integer()}.
45 update(none, _Size) ->
46 4926 {none, 0};
47 update(#shaper{max_rate = MaxRatePerSecond,
48 tokens = LastAvailableTokens,
49 last_update = LastUpdate}, NowUsed) ->
50 22399 Now = erlang:monotonic_time(millisecond),
51 % How much we might have recovered since last time, in milliseconds arithmetic
52 22399 GrowthPerMillisecond = MaxRatePerSecond / 1000,
53 22399 MilliSecondsSinceLastUpdate = (Now - LastUpdate),
54 22399 PossibleTokenGrowth = round(GrowthPerMillisecond * MilliSecondsSinceLastUpdate),
55 % Available plus recovered cannot grow higher than the actual rate limit
56 22399 ExactlyAvailableNow = min(MaxRatePerSecond, LastAvailableTokens + PossibleTokenGrowth),
57 22399 TokensAvailable = max(0, ExactlyAvailableNow - NowUsed),
58 22399 TokensOverused = max(0, NowUsed - ExactlyAvailableNow),
59 22399 MaybeDelay = round(TokensOverused / GrowthPerMillisecond),
60 22399 {#shaper{max_rate = MaxRatePerSecond,
61 tokens = TokensAvailable,
62 last_update = Now + MaybeDelay},
63 MaybeDelay}.
Line Hits Source