11use std:: collections:: HashMap ;
22use std:: time:: Duration ;
33
4+ use deadpool:: managed:: Object ;
45use deno_core:: ModuleCodeString ;
56use serde:: de:: DeserializeOwned ;
67
7- use crate :: orama_extension:: SharedCache ;
8+ use crate :: { orama_extension:: SharedCache , RecyclePolicy } ;
89
910use super :: {
1011 manager:: { ModuleDefinition , WorkerManager } ,
@@ -40,18 +41,34 @@ impl Pool {
4041 Input : TryIntoFunctionParameters + Send + ' static ,
4142 Output : DeserializeOwned + Send + ' static ,
4243 {
43- let mut worker = self . inner . get ( ) . await . map_err ( |e| match e {
44- deadpool:: managed:: PoolError :: Backend ( err) => match err {
45- // The recycle policy of the poll will prevent this
46- RuntimeError :: Dead => unreachable ! ( ) ,
47- _ => RuntimeError :: Unknown ( err. to_string ( ) ) ,
48- } ,
49- _ => RuntimeError :: Unknown ( e. to_string ( ) ) ,
50- } ) ?;
51-
52- worker
44+ let mut worker = self . get_worker ( ) . await ?;
45+ let result = worker
5346 . exec ( module_name, function_name, params, exec_options)
54- . await
47+ . await ;
48+
49+ if let Err ( ref err) = result {
50+ let recycle_policy = self . manager . worker_options . recycle_policy ;
51+
52+ let should_discard = match recycle_policy {
53+ RecyclePolicy :: Never => false ,
54+ RecyclePolicy :: OnTimeout => {
55+ matches ! ( err, RuntimeError :: ExecTimeout )
56+ }
57+ RecyclePolicy :: OnError => !matches ! ( err, RuntimeError :: NetworkPermissionDenied ( _) ) ,
58+ RecyclePolicy :: OnTimeoutOrError => {
59+ matches ! ( err, RuntimeError :: ExecTimeout )
60+ || !matches ! ( err, RuntimeError :: NetworkPermissionDenied ( _) )
61+ }
62+ } ;
63+
64+ if should_discard {
65+ // Take the worker out so it won't be returned to the pool
66+ // This will cause the worker to be dropped and a new one created on next use
67+ let _ = deadpool:: managed:: Object :: take ( worker) ;
68+ }
69+ }
70+
71+ result
5572 }
5673
5774 /// Add or update a module in the pool
@@ -62,20 +79,39 @@ impl Pool {
6279 ) -> Result < ( ) , RuntimeError > {
6380 let name = name. into ( ) ;
6481 let code: ModuleCodeString = code. into ( ) ;
82+ let ( runtime_code, module_code) = code. into_cheap_copy ( ) ;
83+
84+ let worker = self . get_worker ( ) . await ?;
85+ // Take the worker out so it won't be returned to the pool
86+ // This will cause the worker to be dropped and a new one created on next use
87+ // So we do not create inconsistent workers.
88+ let mut worker = deadpool:: managed:: Object :: take ( worker) ;
89+ worker. add_module ( name. clone ( ) , runtime_code) . await ?;
6590
6691 let mut modules = self . manager . modules ( ) ;
6792
6893 modules. insert (
6994 name. clone ( ) ,
7095 ModuleDefinition {
71- code : code . as_str ( ) . into ( ) ,
96+ code : module_code . as_str ( ) . into ( ) ,
7297 } ,
7398 ) ;
7499
75100 self . manager . update_modules ( modules) ;
76101
77102 Ok ( ( ) )
78103 }
104+
105+ async fn get_worker ( & self ) -> Result < Object < WorkerManager > , RuntimeError > {
106+ self . inner . get ( ) . await . map_err ( |e| match e {
107+ deadpool:: managed:: PoolError :: Backend ( err) => match err {
108+ // The recycle policy of the poll will prevent this
109+ RuntimeError :: Dead => unreachable ! ( ) ,
110+ _ => err,
111+ } ,
112+ _ => RuntimeError :: Unknown ( e. to_string ( ) ) ,
113+ } )
114+ }
79115}
80116
81117/// Builder for creating a Pool.
@@ -84,7 +120,7 @@ pub struct PoolBuilder {
84120 max_size : usize ,
85121 domain_permission : Option < DomainPermission > ,
86122 evaluation_timeout : Option < std:: time:: Duration > ,
87- recycle_policy : Option < super :: options :: RecyclePolicy > ,
123+ recycle_policy : Option < RecyclePolicy > ,
88124}
89125
90126impl PoolBuilder {
@@ -118,7 +154,7 @@ impl PoolBuilder {
118154 }
119155
120156 /// Set the recycle policy for all workers
121- pub fn with_recycle_policy ( mut self , policy : super :: options :: RecyclePolicy ) -> Self {
157+ pub fn with_recycle_policy ( mut self , policy : RecyclePolicy ) -> Self {
122158 self . recycle_policy = Some ( policy) ;
123159 self
124160 }
@@ -1117,24 +1153,19 @@ mod tests {
11171153 let pool = Pool :: builder ( )
11181154 . max_size ( 1 )
11191155 . with_evaluation_timeout ( Duration :: from_millis ( 100 ) )
1120- . add_module ( "expensive" , expensive_code. to_string ( ) )
11211156 . build ( )
11221157 . unwrap ( ) ;
11231158
1124- let result: Result < i32 , RuntimeError > = pool
1125- . exec ( "expensive" , "getValue" , ( ) , ExecOptions :: new ( ) )
1159+ let result = pool
1160+ . add_module ( "expensive" , expensive_code . to_string ( ) )
11261161 . await ;
11271162
11281163 assert ! ( result. is_err( ) , "Module evaluation should timeout" ) ;
11291164 assert ! ( matches!( result. unwrap_err( ) , RuntimeError :: InitTimeout ) ) ;
11301165
11311166 // also on adding a module
1132- pool. add_module ( "expensive_2" , expensive_code. to_string ( ) )
1133- . await
1134- . unwrap ( ) ;
1135-
1136- let result: Result < i32 , RuntimeError > = pool
1137- . exec ( "expensive_2" , "getValue" , ( ) , ExecOptions :: new ( ) )
1167+ let result = pool
1168+ . add_module ( "expensive_2" , expensive_code. to_string ( ) )
11381169 . await ;
11391170
11401171 assert ! ( result. is_err( ) , "Module evaluation should timeout" ) ;
@@ -1145,14 +1176,11 @@ mod tests {
11451176 function add(a, b) { return a + b; }
11461177 export default { add };
11471178 "# ;
1148- pool. add_module ( "not_expensive" , add_code. to_string ( ) )
1149- . await
1150- . unwrap ( ) ;
1151-
1152- let result: Result < i32 , RuntimeError > = pool
1153- . exec ( "not_expensive" , "add" , ( 1 , 2 ) , ExecOptions :: new ( ) )
1154- . await ;
1155-
1156- assert ! ( result. is_ok( ) , "Should not error" ) ;
1179+ let result = pool. add_module ( "not_expensive" , add_code. to_string ( ) ) . await ;
1180+ assert ! (
1181+ result. is_ok( ) ,
1182+ "Should not error: {:?}" ,
1183+ result. unwrap_err( )
1184+ ) ;
11571185 }
11581186}
0 commit comments