@@ -24,7 +24,7 @@ use std::sync::Arc;
24
24
use aquatic_udp_protocol:: Response ;
25
25
use derive_more:: Constructor ;
26
26
use log:: { debug, error, info, trace} ;
27
- use ringbuf:: traits:: { Consumer , Observer , RingBuffer } ;
27
+ use ringbuf:: traits:: { Consumer , Observer , Producer } ;
28
28
use ringbuf:: StaticRb ;
29
29
use tokio:: net:: UdpSocket ;
30
30
use tokio:: sync:: oneshot;
@@ -202,11 +202,23 @@ impl Launcher {
202
202
}
203
203
}
204
204
205
- #[ derive( Default ) ]
206
205
struct ActiveRequests {
207
206
rb : StaticRb < AbortHandle , 50 > , // the number of requests we handle at the same time.
208
207
}
209
208
209
+ impl ActiveRequests {
210
+ /// Creates a new [`ActiveRequests`] filled with finished tasks.
211
+ async fn new ( ) -> Self {
212
+ let mut rb = StaticRb :: default ( ) ;
213
+
214
+ let ( ) = while rb. try_push ( tokio:: task:: spawn_blocking ( || ( ) ) . abort_handle ( ) ) . is_ok ( ) { } ;
215
+
216
+ task:: yield_now ( ) . await ;
217
+
218
+ Self { rb }
219
+ }
220
+ }
221
+
210
222
impl std:: fmt:: Debug for ActiveRequests {
211
223
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
212
224
let ( left, right) = & self . rb . as_slices ( ) ;
@@ -280,15 +292,22 @@ impl Udp {
280
292
let tracker = tracker. clone ( ) ;
281
293
let socket = socket. clone ( ) ;
282
294
283
- let reqs = & mut ActiveRequests :: default ( ) ;
295
+ let reqs = & mut ActiveRequests :: new ( ) . await ;
284
296
285
- // Main Waiting Loop, awaits on async [`receive_request`].
286
297
loop {
287
- if let Some ( h) = reqs. rb . push_overwrite (
288
- Self :: spawn_request_processor ( Self :: receive_request ( socket. clone ( ) ) . await , tracker. clone ( ) , socket. clone ( ) )
289
- . abort_handle ( ) ,
290
- ) {
291
- if !h. is_finished ( ) {
298
+ task:: yield_now ( ) . await ;
299
+ for h in reqs. rb . iter_mut ( ) {
300
+ if h. is_finished ( ) {
301
+ std:: mem:: swap (
302
+ h,
303
+ & mut Self :: spawn_request_processor (
304
+ Self :: receive_request ( socket. clone ( ) ) . await ,
305
+ tracker. clone ( ) ,
306
+ socket. clone ( ) ,
307
+ )
308
+ . abort_handle ( ) ,
309
+ ) ;
310
+ } else {
292
311
// the task is still running, lets yield and give it a chance to flush.
293
312
tokio:: task:: yield_now ( ) . await ;
294
313
@@ -299,6 +318,9 @@ impl Udp {
299
318
tracing:: span!(
300
319
target: "UDP TRACKER" ,
301
320
tracing:: Level :: WARN , "request-aborted" , server_socket_addr = %server_socket_addr) ;
321
+
322
+ // force-break a single thread, then loop again.
323
+ break ;
302
324
}
303
325
}
304
326
}
@@ -396,13 +418,46 @@ mod tests {
396
418
use std:: sync:: Arc ;
397
419
use std:: time:: Duration ;
398
420
399
- use tokio :: time :: sleep ;
421
+ use ringbuf :: traits :: { Consumer , Observer , RingBuffer } ;
400
422
use torrust_tracker_test_helpers:: configuration:: ephemeral_mode_public;
401
423
424
+ use super :: ActiveRequests ;
402
425
use crate :: bootstrap:: app:: initialize_with_configuration;
403
426
use crate :: servers:: registar:: Registar ;
404
427
use crate :: servers:: udp:: server:: { Launcher , UdpServer } ;
405
428
429
+ #[ tokio:: test]
430
+ async fn it_should_return_to_the_start_of_the_ring_buffer ( ) {
431
+ let mut a_req = ActiveRequests :: new ( ) . await ;
432
+
433
+ tokio:: time:: sleep ( Duration :: from_millis ( 10 ) ) . await ;
434
+
435
+ let mut count: usize = 0 ;
436
+ let cap: usize = a_req. rb . capacity ( ) . into ( ) ;
437
+
438
+ // Add a single pending task to check that the ring-buffer is looping correctly.
439
+ a_req
440
+ . rb
441
+ . push_overwrite ( tokio:: task:: spawn ( std:: future:: pending :: < ( ) > ( ) ) . abort_handle ( ) ) ;
442
+
443
+ count += 1 ;
444
+
445
+ for _ in 0 ..2 {
446
+ for h in a_req. rb . iter ( ) {
447
+ let first = count % cap;
448
+ println ! ( "{count},{first},{}" , h. is_finished( ) ) ;
449
+
450
+ if first == 0 {
451
+ assert ! ( !h. is_finished( ) ) ;
452
+ } else {
453
+ assert ! ( h. is_finished( ) ) ;
454
+ }
455
+
456
+ count += 1 ;
457
+ }
458
+ }
459
+ }
460
+
406
461
#[ tokio:: test]
407
462
async fn it_should_be_able_to_start_and_stop ( ) {
408
463
let cfg = Arc :: new ( ephemeral_mode_public ( ) ) ;
@@ -423,7 +478,7 @@ mod tests {
423
478
. expect ( "it should start the server" ) ;
424
479
let stopped = started. stop ( ) . await . expect ( "it should stop the server" ) ;
425
480
426
- sleep ( Duration :: from_secs ( 1 ) ) . await ;
481
+ tokio :: time :: sleep ( Duration :: from_secs ( 1 ) ) . await ;
427
482
428
483
assert_eq ! ( stopped. state. launcher. bind_to, bind_to) ;
429
484
}
0 commit comments