11use std:: ops:: Deref ;
2- use std:: thread:: JoinHandle ;
32use std:: time:: Duration ;
43
54use bytes:: Bytes ;
@@ -8,8 +7,10 @@ use openworkers_runtime::RuntimeLimits;
87use openworkers_runtime:: Script ;
98use openworkers_runtime:: Task ;
109use openworkers_runtime:: Worker ;
10+ use tokio:: sync:: OwnedSemaphorePermit ;
1111
1212use crate :: store:: WorkerData ;
13+ use crate :: worker_pool:: WORKER_POOL ;
1314
1415type ResTx = tokio:: sync:: oneshot:: Sender < http_v02:: Response < Bytes > > ;
1516
@@ -21,7 +22,8 @@ pub fn run_fetch(
2122 req : http_v02:: Request < Bytes > ,
2223 res_tx : ResTx ,
2324 global_log_tx : std:: sync:: mpsc:: Sender < crate :: log:: LogMessage > ,
24- ) -> JoinHandle < ( ) > {
25+ permit : OwnedSemaphorePermit ,
26+ ) {
2527 let ( log_tx, log_handler) = crate :: log:: create_log_handler ( worker. id . clone ( ) , global_log_tx) ;
2628
2729 let script = Script {
@@ -32,63 +34,56 @@ pub fn run_fetch(
3234 } ,
3335 } ;
3436
35- std:: thread:: spawn ( move || {
36- let local = tokio:: task:: LocalSet :: new ( ) ;
37-
38- let tasks = local. spawn_local ( async move {
39- log:: debug!( "create worker" ) ;
40-
41- let limits = RuntimeLimits {
42- max_cpu_time_ms : 100 , // 100ms CPU time for fetch tasks
43- max_wall_clock_time_ms : 60_000 , // 60s total time for fetch tasks
44- ..Default :: default ( )
45- } ;
46-
47- let mut worker = match Worker :: new ( script, Some ( log_tx) , Some ( limits) ) . await {
48- Ok ( worker) => worker,
49- Err ( err) => {
50- log:: error!( "failed to create worker: {err}" ) ;
51- res_tx
52- . send (
53- http_v02:: Response :: builder ( )
54- . status ( 500 )
55- . body ( format ! ( "failed to create worker: {err}" ) . into ( ) )
56- . unwrap ( ) ,
57- )
58- . unwrap ( ) ;
59-
60- return ;
61- }
62- } ;
63-
64- let task = Task :: Fetch ( Some ( FetchInit :: new ( req, res_tx) ) ) ;
65-
66- log:: debug!( "exec fetch task with {}ms timeout" , FETCH_TIMEOUT_MS ) ;
67-
68- // Wrap execution with timeout
69- let timeout_duration = Duration :: from_millis ( FETCH_TIMEOUT_MS ) ;
70- match tokio:: time:: timeout ( timeout_duration, worker. exec ( task) ) . await {
71- Ok ( Ok ( ( ) ) ) => log:: debug!( "exec completed" ) ,
72- Ok ( Err ( err) ) => log:: error!( "exec did not complete: {err}" ) ,
73- Err ( _) => {
74- log:: error!( "exec timeout after {}ms" , FETCH_TIMEOUT_MS ) ;
75- // Note: Worker may have already sent a response via FetchInit
76- // If no response was sent, res_tx will be dropped and client gets an error
77- }
37+ // Use the global worker pool instead of spawning a new thread
38+ WORKER_POOL . spawn_pinned ( move || async move {
39+ // Keep the permit alive for the entire worker execution
40+ // It will be automatically released when this async block completes
41+ let _permit = permit;
42+
43+ log:: debug!( "create worker" ) ;
44+
45+ let limits = RuntimeLimits {
46+ max_cpu_time_ms : 100 , // 100ms CPU time for fetch tasks
47+ max_wall_clock_time_ms : 60_000 , // 60s total time for fetch tasks
48+ ..Default :: default ( )
49+ } ;
50+
51+ let mut worker = match Worker :: new ( script, Some ( log_tx) , Some ( limits) ) . await {
52+ Ok ( worker) => worker,
53+ Err ( err) => {
54+ log:: error!( "failed to create worker: {err}" ) ;
55+ res_tx
56+ . send (
57+ http_v02:: Response :: builder ( )
58+ . status ( 500 )
59+ . body ( format ! ( "failed to create worker: {err}" ) . into ( ) )
60+ . unwrap ( ) ,
61+ )
62+ . unwrap ( ) ;
63+
64+ return ;
7865 }
66+ } ;
7967
80- // CRITICAL: Flush logs before worker is dropped to prevent log loss
81- log_handler. flush ( ) ;
82- } ) ;
68+ let task = Task :: Fetch ( Some ( FetchInit :: new ( req, res_tx) ) ) ;
8369
84- let rt = tokio:: runtime:: Builder :: new_current_thread ( )
85- . enable_all ( )
86- . build ( )
87- . unwrap ( ) ;
70+ log:: debug!( "exec fetch task with {}ms timeout" , FETCH_TIMEOUT_MS ) ;
8871
89- match local. block_on ( & rt, tasks) {
90- Ok ( ( ) ) => { }
91- Err ( err) => log:: error!( "failed to wait for end: {err}" ) ,
72+ // Wrap execution with timeout
73+ let timeout_duration = Duration :: from_millis ( FETCH_TIMEOUT_MS ) ;
74+ match tokio:: time:: timeout ( timeout_duration, worker. exec ( task) ) . await {
75+ Ok ( Ok ( ( ) ) ) => log:: debug!( "exec completed" ) ,
76+ Ok ( Err ( err) ) => log:: error!( "exec did not complete: {err}" ) ,
77+ Err ( _) => {
78+ log:: error!( "exec timeout after {}ms" , FETCH_TIMEOUT_MS ) ;
79+ // Note: Worker may have already sent a response via FetchInit
80+ // If no response was sent, res_tx will be dropped and client gets an error
81+ }
9282 }
93- } )
83+
84+ // CRITICAL: Flush logs before worker is dropped to prevent log loss
85+ log_handler. flush ( ) ;
86+
87+ // Permit is automatically released here when _permit goes out of scope
88+ } ) ;
9489}
0 commit comments