8
8
-behaviour (gen_server ).
9
9
10
10
-define (SERVER , ? MODULE ).
11
+ -define (DEFAULT_USER_RATE , 1200 ).
11
12
12
- -required_variable (#{name => interarrival , default_value => 50 ,
13
- verification => {? MODULE , non_neg_integer , 1 },
14
- description => " a delay between creating the processes for two "
15
- " consecutive users (ms, def: 50ms)" ,
16
- update => {? MODULE , maybe_update_interarrival_timer , 2 }}).
13
+ -required_variable (#{name => user_rate , default_value => ? DEFAULT_USER_RATE ,
14
+ verification => {? MODULE , verify_user_rate , 1 },
15
+ description => " Throttle rate for the Scenario:start/1,2 callback" ,
16
+ update => {? MODULE , update_user_rate , 2 }}).
17
17
18
18
-record (state , {scenario :: amoc :scenario () | undefined ,
19
+ status = idle :: status (),
19
20
last_user_id = 0 :: last_user_id (),
20
- status = idle :: idle | running | terminating | finished |
21
- { error , any ()} | disabled ,
22
- scenario_state :: any (), % % state returned from Scenario:init/0
23
- create_users = [] :: [ amoc_scenario : user_id ()],
24
- tref :: timer : tref () | undefined }) .
21
+ scenario_state :: amoc_scenario : state () % % state returned from Scenario:init/0
22
+ }).
23
+
24
+ - type status () :: idle | running | terminating | finished | { error , any ()} | disabled .
25
+ % % Scenario status .
25
26
26
27
-type state () :: # state {}.
27
28
% % Internal state of the node's controller
29
+
28
30
-type handle_call_res () :: ok | {ok , term ()} | {error , term ()}.
29
31
-type running_status () :: #{scenario := amoc :scenario (),
30
32
currently_running_users := user_count (),
31
33
highest_user_id := last_user_id ()}.
32
34
% % Details about the scenario currently running
35
+
33
36
-type amoc_status () :: idle |
34
37
{running , running_status ()} |
35
38
{terminating , amoc :scenario ()} |
36
39
{finished , amoc :scenario ()} |
37
40
{error , any ()} |
38
41
disabled .
39
42
% % Status of the node, note that amoc_controller is disabled for the master node
43
+
40
44
-type user_count () :: non_neg_integer ().
41
45
% % Number of users currently running in the node
46
+
42
47
-type last_user_id () :: non_neg_integer ().
43
48
% % Highest user id registered in the node
44
- -type interarrival () :: non_neg_integer ().
49
+
50
+ -type user_rate () :: amoc_throttle :rate ().
45
51
% % Time to wait in between spawning new users
46
52
47
53
% % ------------------------------------------------------------------
65
71
% % ------------------------------------------------------------------
66
72
% % Parameters verification functions
67
73
% % ------------------------------------------------------------------
68
- -export ([maybe_update_interarrival_timer /2 , non_neg_integer /1 ]).
74
+ -export ([update_user_rate /2 , verify_user_rate /1 ]).
69
75
70
- -export ([zero_users_running /0 ]).
76
+ -export ([wait_user_rate / 0 , zero_users_running /0 ]).
71
77
72
78
% % ------------------------------------------------------------------
73
79
% % gen_server Function Exports
74
80
% % ------------------------------------------------------------------
75
- -export ([init /1 , handle_call /3 , handle_cast /2 , handle_info /2 ]).
81
+ -export ([init /1 , handle_call /3 , handle_cast /2 , handle_info /2 , terminate / 2 ]).
76
82
77
83
% % ------------------------------------------------------------------
78
84
% % API Function Definitions
@@ -122,14 +128,14 @@ disable() ->
122
128
gen_server :call (? SERVER , disable ).
123
129
124
130
% % @private
125
- -spec non_neg_integer (any ()) -> boolean ().
126
- non_neg_integer ( Interarrival ) ->
127
- is_integer (Interarrival ) andalso Interarrival >= 0 .
131
+ -spec verify_user_rate (any ()) -> boolean ().
132
+ verify_user_rate ( UserRate ) ->
133
+ ( is_integer (UserRate ) andalso ( 0 =< UserRate )) orelse ( infinity =:= UserRate ) .
128
134
129
135
% % @private
130
- -spec maybe_update_interarrival_timer ( interarrival , term ()) -> ok .
131
- maybe_update_interarrival_timer ( interarrival , _ ) ->
132
- gen_server : cast ( ? SERVER , maybe_update_interarrival_timer ).
136
+ -spec update_user_rate ( user_rate , user_rate ()) -> ok .
137
+ update_user_rate ( user_rate , UserRate ) ->
138
+ ok = amoc_throttle : change_rate ( user_rate , #{ rate => UserRate } ).
133
139
134
140
% % @private
135
141
-spec zero_users_running () -> ok .
@@ -180,8 +186,6 @@ handle_call(_Request, _From, State) ->
180
186
181
187
% % @private
182
188
-spec handle_cast (any (), state ()) -> {noreply , state ()}.
183
- handle_cast (maybe_update_interarrival_timer , State ) ->
184
- {noreply , maybe_update_interarrival_timer (State )};
185
189
handle_cast (zero_users_running , State ) ->
186
190
NewSate = handle_zero_users_running (State ),
187
191
{noreply , NewSate };
@@ -190,15 +194,14 @@ handle_cast(_Msg, State) ->
190
194
191
195
% % @private
192
196
-spec handle_info (any (), state ()) -> {noreply , state ()}.
193
- handle_info (start_user , State ) ->
194
- NewSate = handle_start_user (State ),
195
- {noreply , NewSate };
196
- handle_info (start_all_users , State ) ->
197
- NewSate = handle_start_all_users (State ),
198
- {noreply , NewSate };
199
197
handle_info (_Msg , State ) ->
200
198
{noreply , State }.
201
199
200
+ % % @private
201
+ -spec terminate (term (), state ()) -> any ().
202
+ terminate (_Reason , _State ) ->
203
+ amoc_users_sup :terminate_all_children ().
204
+
202
205
% % ------------------------------------------------------------------
203
206
% % internal functions
204
207
% % ------------------------------------------------------------------
@@ -243,18 +246,15 @@ handle_update_settings(_Settings, #state{status = Status}) ->
243
246
244
247
-spec handle_add (amoc_scenario :user_id (), amoc_scenario :user_id (), state ()) ->
245
248
{handle_call_res (), state ()}.
246
- handle_add (StartId , EndId , # state {last_user_id = LastId ,
247
- create_users = ScheduledUsers ,
248
- status = running ,
249
+ handle_add (StartId , EndId , # state {status = running ,
250
+ last_user_id = LastId ,
249
251
scenario = Scenario ,
250
- tref = TRef } = State ) when StartId =< EndId ,
251
- LastId < StartId ->
252
+ scenario_state = ScenarioState } = State )
253
+ when StartId =< EndId , LastId < StartId ->
252
254
amoc_telemetry :execute ([controller , users ], #{count => EndId - StartId + 1 },
253
255
#{scenario => Scenario , type => add }),
254
- NewUsers = lists :seq (StartId , EndId ),
255
- NewScheduledUsers = lists :append (ScheduledUsers , NewUsers ),
256
- NewTRef = maybe_start_timer (TRef ),
257
- {ok , State # state {create_users = NewScheduledUsers , tref = NewTRef , last_user_id = EndId }};
256
+ amoc_users_sup :start_children (Scenario , StartId , EndId , ScenarioState ),
257
+ {ok , State # state {last_user_id = EndId }};
258
258
handle_add (_StartId , _EndId , # state {status = running } = State ) ->
259
259
{{error , invalid_range }, State };
260
260
handle_add (_StartId , _EndId , # state {status = Status } = State ) ->
@@ -287,23 +287,6 @@ handle_disable(#state{status = idle} = State) ->
287
287
handle_disable (# state {status = Status } = State ) ->
288
288
{{error , {invalid_status , Status }}, State }.
289
289
290
- -spec handle_start_user (state ()) -> state ().
291
- handle_start_user (# state {create_users = [UserId | T ],
292
- scenario = Scenario ,
293
- scenario_state = ScenarioState } = State ) ->
294
- amoc_users_sup :start_child (Scenario , UserId , ScenarioState ),
295
- State # state {create_users = T };
296
- handle_start_user (# state {create_users = [], tref = TRef } = State ) ->
297
- State # state {tref = maybe_stop_timer (TRef )}.
298
-
299
- -spec handle_start_all_users (state ()) -> state ().
300
- handle_start_all_users (# state {create_users = AllUsers ,
301
- scenario = Scenario ,
302
- scenario_state = ScenarioState ,
303
- tref = TRef } = State ) ->
304
- amoc_users_sup :start_children (Scenario , AllUsers , ScenarioState ),
305
- State # state {create_users = [], tref = maybe_stop_timer (TRef )}.
306
-
307
290
% % ------------------------------------------------------------------
308
291
% % helpers
309
292
% % ------------------------------------------------------------------
@@ -316,12 +299,15 @@ start_tables() -> %% ETS creation
316
299
{ok | error , any ()}.
317
300
init_scenario (Scenario , Settings ) ->
318
301
case amoc_config_scenario :parse_scenario_settings (Scenario , Settings ) of
319
- ok -> amoc_scenario :init (Scenario );
302
+ ok ->
303
+ start_user_rate (),
304
+ amoc_scenario :init (Scenario );
320
305
{error , Type , Reason } -> {error , {Type , Reason }}
321
306
end .
322
307
323
308
-spec terminate_scenario (state ()) -> ok | {ok , any ()} | {error , any ()}.
324
309
terminate_scenario (# state {scenario = Scenario , scenario_state = ScenarioState }) ->
310
+ stop_user_rate (),
325
311
amoc_scenario :terminate (Scenario , ScenarioState ).
326
312
327
313
-spec handle_zero_users_running (state ()) -> state ().
@@ -331,35 +317,20 @@ handle_zero_users_running(#state{status = terminating} = State) ->
331
317
handle_zero_users_running (State ) ->
332
318
State .
333
319
334
- -spec maybe_stop_timer (timer :tref () | undefined ) -> undefined .
335
- maybe_stop_timer (undefined ) ->
336
- undefined ;
337
- maybe_stop_timer (TRef ) ->
338
- {ok , cancel } = timer :cancel (TRef ),
339
- undefined .
340
-
341
- -spec get_interarrival () -> interarrival ().
342
- get_interarrival () ->
343
- amoc_config :get (interarrival ).
344
-
345
- -spec maybe_update_interarrival_timer (state ()) -> state ().
346
- maybe_update_interarrival_timer (# state {tref = undefined } = State ) ->
347
- State ;
348
- maybe_update_interarrival_timer (# state {tref = TRef } = State ) ->
349
- {ok , cancel } = timer :cancel (TRef ),
350
- Value = get_interarrival (),
351
- NewTRef = do_interarrival (Value ),
352
- State # state {tref = NewTRef }.
353
-
354
- -spec maybe_start_timer (timer :tref () | undefined ) -> timer :tref ().
355
- maybe_start_timer (undefined ) ->
356
- Value = get_interarrival (),
357
- do_interarrival (Value );
358
- maybe_start_timer (TRef ) -> TRef .
359
-
360
- do_interarrival (0 ) ->
361
- self () ! start_all_users ,
362
- undefined ;
363
- do_interarrival (Value ) ->
364
- {ok , NewTRef } = timer :send_interval (Value , start_user ),
365
- NewTRef .
320
+ -spec get_user_rate () -> user_rate ().
321
+ get_user_rate () ->
322
+ amoc_config :get (user_rate , ? DEFAULT_USER_RATE ).
323
+
324
+ -spec wait_user_rate () -> boolean ().
325
+ wait_user_rate () ->
326
+ infinity =:= get_user_rate ()
327
+ orelse ok =:= amoc_throttle :wait (user_rate ).
328
+
329
+ -spec start_user_rate () -> any ().
330
+ start_user_rate () ->
331
+ UserRate = get_user_rate (),
332
+ amoc_throttle :start (user_rate , #{rate => UserRate }).
333
+
334
+ -spec stop_user_rate () -> any ().
335
+ stop_user_rate () ->
336
+ amoc_throttle :stop (user_rate ).
0 commit comments