@@ -9,7 +9,7 @@ use crate::{orama_extension::SharedCache, RecyclePolicy};
99
1010use super :: {
1111 manager:: { ModuleDefinition , WorkerManager } ,
12- options:: { DomainPermission , ExecOptions , WorkerOptions } ,
12+ options:: { DomainPermission , ExecOptions , MaxExecutions , WorkerOptions } ,
1313 parameters:: TryIntoFunctionParameters ,
1414 runtime:: RuntimeError ,
1515 worker:: WorkerBuilder ,
@@ -138,7 +138,7 @@ pub struct PoolBuilder {
138138 domain_permission : Option < DomainPermission > ,
139139 evaluation_timeout : Option < std:: time:: Duration > ,
140140 recycle_policy : Option < RecyclePolicy > ,
141- max_executions : Option < u64 > ,
141+ max_executions : Option < MaxExecutions > ,
142142}
143143
144144impl PoolBuilder {
@@ -150,7 +150,7 @@ impl PoolBuilder {
150150 domain_permission : None ,
151151 evaluation_timeout : None ,
152152 recycle_policy : None ,
153- max_executions : Some ( 100 ) ,
153+ max_executions : None ,
154154 }
155155 }
156156
@@ -178,9 +178,8 @@ impl PoolBuilder {
178178 self
179179 }
180180
181- /// Set the maximum number of executions before recycling the runtime
182- /// to prevent memory leaks from accumulated module cache.
183- pub fn with_max_executions ( mut self , max : u64 ) -> Self {
181+ /// Set the maximum number of executions before recycling workers in the pool.
182+ pub fn with_max_executions ( mut self , max : MaxExecutions ) -> Self {
184183 self . max_executions = Some ( max) ;
185184 self
186185 }
@@ -209,7 +208,7 @@ impl PoolBuilder {
209208 evaluation_timeout : self . evaluation_timeout . unwrap_or ( Duration :: from_secs ( 5 ) ) ,
210209 domain_permission : self . domain_permission . unwrap_or_default ( ) ,
211210 recycle_policy : self . recycle_policy . unwrap_or_default ( ) ,
212- max_executions : self . max_executions ,
211+ max_executions : self . max_executions . unwrap_or_default ( ) ,
213212 } ;
214213
215214 // Validate that all modules can be loaded within the evaluation timeout
@@ -1468,4 +1467,57 @@ mod tests {
14681467 RuntimeError :: MissingModule ( name) if name == "nonexistent"
14691468 ) ) ;
14701469 }
1470+
1471+ #[ tokio:: test]
1472+ async fn test_pool_max_executions ( ) {
1473+ let _ = tracing_subscriber:: fmt:: try_init ( ) ;
1474+
1475+ let counter_code = r#"
1476+ let callCount = 0;
1477+ function increment() {
1478+ callCount++;
1479+ return callCount;
1480+ }
1481+ export default { increment };
1482+ "# ;
1483+
1484+ let pool = Pool :: builder ( )
1485+ . max_size ( 1 )
1486+ . add_module ( "counter" , counter_code. to_string ( ) )
1487+ . with_max_executions ( MaxExecutions :: Limited ( 2 ) )
1488+ . build ( )
1489+ . await
1490+ . unwrap ( ) ;
1491+
1492+ // First 3 executions should increment the counter
1493+ let result1: i32 = pool
1494+ . exec ( "counter" , "increment" , ( ) , ExecOptions :: new ( ) )
1495+ . await
1496+ . unwrap ( ) ;
1497+ assert_eq ! ( result1, 1 ) ;
1498+
1499+ let result2: i32 = pool
1500+ . exec ( "counter" , "increment" , ( ) , ExecOptions :: new ( ) )
1501+ . await
1502+ . unwrap ( ) ;
1503+ assert_eq ! ( result2, 2 ) ;
1504+
1505+ // After 2 executions, the worker should be recycled
1506+ // and the counter should reset to 1
1507+ let result4: i32 = pool
1508+ . exec ( "counter" , "increment" , ( ) , ExecOptions :: new ( ) )
1509+ . await
1510+ . unwrap ( ) ;
1511+ assert_eq ! (
1512+ result4, 1 ,
1513+ "Counter should reset after max_executions is reached"
1514+ ) ;
1515+
1516+ // Verify it continues to work correctly after recycling
1517+ let result5: i32 = pool
1518+ . exec ( "counter" , "increment" , ( ) , ExecOptions :: new ( ) )
1519+ . await
1520+ . unwrap ( ) ;
1521+ assert_eq ! ( result5, 2 ) ;
1522+ }
14711523}
0 commit comments