@@ -26,16 +26,19 @@ use ext_workers::context::UserWorkerProfile;
26
26
use ext_workers:: context:: WorkerContextInitOpts ;
27
27
use ext_workers:: context:: WorkerRuntimeOpts ;
28
28
use ext_workers:: errors:: WorkerError ;
29
+ use futures_util:: future:: join_all;
29
30
use http_v02:: Request ;
30
31
use hyper_v014:: Body ;
31
32
use log:: error;
32
33
use tokio:: sync:: mpsc;
33
34
use tokio:: sync:: mpsc:: UnboundedSender ;
35
+ use tokio:: sync:: oneshot;
34
36
use tokio:: sync:: oneshot:: Sender ;
35
37
use tokio:: sync:: Notify ;
36
38
use tokio:: sync:: OwnedSemaphorePermit ;
37
39
use tokio:: sync:: Semaphore ;
38
40
use tokio:: sync:: TryAcquireError ;
41
+ use tokio:: time:: timeout;
39
42
use tokio_util:: sync:: CancellationToken ;
40
43
use uuid:: Uuid ;
41
44
@@ -442,6 +445,7 @@ impl WorkerPool {
442
445
is_retired : Arc :: new ( AtomicFlag :: default ( ) ) ,
443
446
} ;
444
447
448
+ let ( early_drop_tx, early_drop_rx) = mpsc:: unbounded_channel ( ) ;
445
449
let ( req_end_timing_tx, req_end_timing_rx) =
446
450
mpsc:: unbounded_channel :: < ( ) > ( ) ;
447
451
@@ -453,6 +457,7 @@ impl WorkerPool {
453
457
user_worker_rt_opts. cancel = Some ( cancel. clone ( ) ) ;
454
458
455
459
worker_options. timing = Some ( Timing {
460
+ early_drop_rx,
456
461
status : status. clone ( ) ,
457
462
req : ( req_start_timing_rx, req_end_timing_rx) ,
458
463
} ) ;
@@ -472,6 +477,7 @@ impl WorkerPool {
472
477
Ok ( surface) => {
473
478
let profile = UserWorkerProfile {
474
479
worker_request_msg_tx : surface. msg_tx ,
480
+ early_drop_tx,
475
481
timing_tx_pair : ( req_start_timing_tx, req_end_timing_tx) ,
476
482
service_path,
477
483
permit : permit. map ( Arc :: new) ,
@@ -656,6 +662,24 @@ impl WorkerPool {
656
662
self . metric_src . decl_active_user_workers ( ) ;
657
663
}
658
664
665
+ async fn try_cleanup_idle_workers ( & mut self , timeout_ms : usize ) -> usize {
666
+ let mut rxs = vec ! [ ] ;
667
+ for profile in self . user_workers . values_mut ( ) {
668
+ let ( tx, rx) = oneshot:: channel ( ) ;
669
+ if profile. early_drop_tx . send ( tx) . is_ok ( ) {
670
+ rxs. push ( timeout ( Duration :: from_millis ( timeout_ms as u64 ) , rx) ) ;
671
+ }
672
+ }
673
+
674
+ join_all ( rxs)
675
+ . await
676
+ . into_iter ( )
677
+ . filter_map ( |it| it. ok ( ) )
678
+ . map ( |it| it. unwrap_or_default ( ) )
679
+ . filter ( |it| * it)
680
+ . count ( )
681
+ }
682
+
659
683
fn retire ( & mut self , key : & Uuid ) {
660
684
if let Some ( profile) = self . user_workers . get_mut ( key) {
661
685
let registry = self
@@ -795,6 +819,10 @@ pub async fn create_user_worker_pool(
795
819
break ;
796
820
}
797
821
}
822
+
823
+ Some ( UserWorkerMsgs :: TryCleanupIdleWorkers ( timeout_ms, res_tx) ) => {
824
+ let _ = res_tx. send( worker_pool. try_cleanup_idle_workers( timeout_ms) . await ) ;
825
+ }
798
826
}
799
827
}
800
828
}
0 commit comments