@@ -26,16 +26,19 @@ use ext_workers::context::UserWorkerProfile;
2626use ext_workers:: context:: WorkerContextInitOpts ;
2727use ext_workers:: context:: WorkerRuntimeOpts ;
2828use ext_workers:: errors:: WorkerError ;
29+ use futures_util:: future:: join_all;
2930use http_v02:: Request ;
3031use hyper_v014:: Body ;
3132use log:: error;
3233use tokio:: sync:: mpsc;
3334use tokio:: sync:: mpsc:: UnboundedSender ;
35+ use tokio:: sync:: oneshot;
3436use tokio:: sync:: oneshot:: Sender ;
3537use tokio:: sync:: Notify ;
3638use tokio:: sync:: OwnedSemaphorePermit ;
3739use tokio:: sync:: Semaphore ;
3840use tokio:: sync:: TryAcquireError ;
41+ use tokio:: time:: timeout;
3942use tokio_util:: sync:: CancellationToken ;
4043use uuid:: Uuid ;
4144
@@ -442,6 +445,7 @@ impl WorkerPool {
442445 is_retired : Arc :: new ( AtomicFlag :: default ( ) ) ,
443446 } ;
444447
448+ let ( early_drop_tx, early_drop_rx) = mpsc:: unbounded_channel ( ) ;
445449 let ( req_end_timing_tx, req_end_timing_rx) =
446450 mpsc:: unbounded_channel :: < ( ) > ( ) ;
447451
@@ -453,6 +457,7 @@ impl WorkerPool {
453457 user_worker_rt_opts. cancel = Some ( cancel. clone ( ) ) ;
454458
455459 worker_options. timing = Some ( Timing {
460+ early_drop_rx,
456461 status : status. clone ( ) ,
457462 req : ( req_start_timing_rx, req_end_timing_rx) ,
458463 } ) ;
@@ -472,6 +477,7 @@ impl WorkerPool {
472477 Ok ( surface) => {
473478 let profile = UserWorkerProfile {
474479 worker_request_msg_tx : surface. msg_tx ,
480+ early_drop_tx,
475481 timing_tx_pair : ( req_start_timing_tx, req_end_timing_tx) ,
476482 service_path,
477483 permit : permit. map ( Arc :: new) ,
@@ -656,6 +662,24 @@ impl WorkerPool {
656662 self . metric_src . decl_active_user_workers ( ) ;
657663 }
658664
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+
659683 fn retire ( & mut self , key : & Uuid ) {
660684 if let Some ( profile) = self . user_workers . get_mut ( key) {
661685 let registry = self
@@ -795,6 +819,10 @@ pub async fn create_user_worker_pool(
795819 break ;
796820 }
797821 }
822+
823+ Some ( UserWorkerMsgs :: TryCleanupIdleWorkers ( timeout_ms, res_tx) ) => {
824+ let _ = res_tx. send( worker_pool. try_cleanup_idle_workers( timeout_ms) . await ) ;
825+ }
798826 }
799827 }
800828 }
0 commit comments