3
3
-module (amoc_throttle ).
4
4
5
5
% % API
6
- -export ([start /2 ,
7
- start /3 ,
8
- start /4 ,
9
- send /3 ,
10
- send /2 ,
11
- send_and_wait /2 ,
12
- wait /1 ,
13
- run /2 ,
14
- pause /1 ,
15
- resume /1 ,
16
- change_rate /3 ,
17
- change_rate_gradually /6 ,
18
- stop /1 ]).
19
-
20
- -deprecated ([{send_and_wait , 2 , " use wait/1 instead" }]).
21
-
22
- -define (DEFAULT_NO_PROCESSES , 10 ).
23
- -define (DEFAULT_INTERVAL , 60000 ). % % one minute
24
- -define (NONNEG_INT (N ), (is_integer (N ) andalso N >= 0 )).
25
- -define (POS_INT (N ), (is_integer (N ) andalso N > 0 )).
6
+ -export ([start /2 , start /3 , start /4 , stop /1 ,
7
+ send /2 , send /3 , send_and_wait /2 , wait /1 ,
8
+ run /2 , pause /1 , resume /1 ,
9
+ change_rate /2 , change_rate /3 ,
10
+ change_rate_gradually /2 , change_rate_gradually /6 ]).
11
+
12
+ -deprecated ([
13
+ {start , 3 , " use start/2 with a config" },
14
+ {start , 4 , " use start/2 with a config" },
15
+ {send_and_wait , 2 , " use wait/1 instead" }
16
+ ]).
26
17
27
18
-type name () :: atom ().
28
19
-type rate () :: pos_integer ().
29
20
-type interval () :: non_neg_integer ().
30
21
% % In milliseconds, defaults to 60000 (one minute) when not given.
31
22
% % An interval of 0 means no delay at all, only the number of simultaneous executions will be
32
23
% % controlled, which corresponds to the number of processes started
33
- -export_type ([name / 0 , rate / 0 , interval / 0 ]).
24
+ -type throttle () :: #{rate := rate (),
25
+ interval := interval ()}.
26
+ % % Throttle unit of measurement
27
+ -type config () :: #{rate := rate (),
28
+ interval => interval (),
29
+ parallelism => non_neg_integer ()}.
30
+ % % Literal throttle configuration
31
+ -type gradual_rate_config () :: #{from_rate := rate (),
32
+ to_rate := rate (),
33
+ interval => interval (),
34
+ step_interval => pos_integer (),
35
+ step_size => pos_integer (),
36
+ step_count => pos_integer (),
37
+ duration => pos_integer ()}.
38
+ % % Configuration for a gradual throttle rate change
39
+ % %
40
+ % % `From' and `To' rates are required. `interval' defaults to 1s and `step_size' to 1 (or -1 if applies),
41
+ % % that is, the throttle will be changed in increments of 1.
42
+ % %
43
+ % % All other values can be calculated from the provided.
44
+
45
+ -export_type ([name / 0 , rate / 0 , interval / 0 , throttle / 0 , config / 0 , gradual_rate_config / 0 ]).
34
46
35
47
% % @see start/4
36
- -spec start (name (), rate ()) -> ok | {error , any ()}.
48
+ -spec start (name (), config () | rate ()) -> {ok , started | already_started } | {error , any ()}.
49
+ start (Name , #{} = Config ) ->
50
+ amoc_throttle_controller :ensure_throttle_processes_started (Name , Config );
37
51
start (Name , Rate ) ->
38
- start (Name , Rate , ? DEFAULT_INTERVAL ).
52
+ amoc_throttle_controller : ensure_throttle_processes_started (Name , #{ rate => Rate } ).
39
53
40
54
% % @see start/4
41
- -spec start (name (), rate (), non_neg_integer ()) -> ok | {error , any ()}.
55
+ -spec start (name (), rate (), non_neg_integer ()) -> { ok , started | already_started } | {error , any ()}.
42
56
start (Name , Rate , Interval ) ->
43
- start (Name , Rate , Interval , ? DEFAULT_NO_PROCESSES ).
57
+ Config = #{rate => Rate , interval => Interval },
58
+ amoc_throttle_controller :ensure_throttle_processes_started (Name , Config ).
44
59
45
60
% % @doc Starts the throttle mechanism for a given `Name' with a given `Rate' per `Interval'.
46
61
% %
47
62
% % The optional arguments are an `Interval' (default is one minute) and a ` NoOfProcesses' (default is 10).
48
63
% % `Name' is needed to identify the rate as a single test can have different rates for different tasks.
49
64
% % `Interval' is given in milliseconds and can be changed to a different value for convenience or higher granularity.
50
65
% % It also accepts a special value of `0' which limits the number of parallel executions associated with `Name' to `Rate'.
51
- -spec start (name (), rate (), interval (), pos_integer ()) -> ok | {error , any ()}.
52
- start (Name , Rate , Interval , NoOfProcesses )
53
- when is_atom (Name ), ? POS_INT (Rate ), ? NONNEG_INT (Interval ), ? POS_INT (NoOfProcesses ) ->
54
- amoc_throttle_controller :ensure_throttle_processes_started (Name , Rate , Interval , NoOfProcesses );
55
- start (_Name , _Rate , _Interval , _NoOfProcesses ) ->
56
- {error , invalid_throttle }.
66
+ -spec start (name (), rate (), interval (), pos_integer ()) ->
67
+ {ok , started | already_started } | {error , any ()}.
68
+ start (Name , Rate , Interval , NoOfProcesses ) ->
69
+ Config = #{rate => Rate , interval => Interval , parallelism => NoOfProcesses },
70
+ amoc_throttle_controller :ensure_throttle_processes_started (Name , Config ).
57
71
58
72
% % @doc Pauses executions for the given `Name' as if `Rate' was set to `0'.
59
73
% %
@@ -67,10 +81,15 @@ pause(Name) ->
67
81
resume (Name ) ->
68
82
amoc_throttle_controller :resume (Name ).
69
83
70
- % % @doc Sets `Rate' and `Interval ' for `Name' according to the given values.
84
+ % % @doc Sets `Throttle ' for `Name' according to the given values.
71
85
% %
72
86
% % Can change whether Amoc throttle limits `Name' to parallel executions or to `Rate' per `Interval',
73
87
% % according to the given `Interval' value.
88
+ -spec change_rate (name (), throttle ()) -> ok | {error , any ()}.
89
+ change_rate (Name , #{rate := Rate , interval := Interval }) ->
90
+ amoc_throttle_controller :change_rate (Name , Rate , Interval ).
91
+
92
+ % % @see change_rate/2
74
93
-spec change_rate (name (), rate (), interval ()) -> ok | {error , any ()}.
75
94
change_rate (Name , Rate , Interval ) ->
76
95
amoc_throttle_controller :change_rate (Name , Rate , Interval ).
@@ -83,12 +102,20 @@ change_rate(Name, Rate, Interval) ->
83
102
% % The rate is calculated at each step in relation to the `RateInterval', which can also be `0'.
84
103
% % There will be `NoOfSteps' steps, each taking `StepInterval' time in milliseconds.
85
104
% %
86
- % % Be aware that, at first, the rate will be changed to `FromRate' per `RateInterval' and this is not considered a step.
105
+ % % Be aware that, at first, the rate will be changed to `FromRate' per `RateInterval'
106
+ % % and this is not considered a step.
107
+ -spec change_rate_gradually (name (), gradual_rate_config ()) ->
108
+ ok | {error , any ()}.
109
+ change_rate_gradually (Name , Config ) ->
110
+ amoc_throttle_controller :change_rate_gradually (Name , Config ).
111
+
112
+ % % @see change_rate_gradually/2
87
113
-spec change_rate_gradually (name (), rate (), rate (), interval (), pos_integer (), pos_integer ()) ->
88
114
ok | {error , any ()}.
89
- change_rate_gradually (Name , FromRate , ToRate , RateInterval , StepInterval , NoOfSteps ) ->
90
- amoc_throttle_controller :change_rate_gradually (
91
- Name , FromRate , ToRate , RateInterval , StepInterval , NoOfSteps ).
115
+ change_rate_gradually (Name , FromRate , ToRate , RateInterval , StepInterval , StepCount ) ->
116
+ Config = #{from_rate => FromRate , to_rate => ToRate , interval => RateInterval ,
117
+ step_interval => StepInterval , step_count => StepCount },
118
+ amoc_throttle_controller :change_rate_gradually (Name , Config ).
92
119
93
120
% % @doc Executes a given function `Fn' when it does not exceed the rate for `Name'.
94
121
% %
0 commit comments