From 6c720fb16a57d4dee6b0cdcd782e72c0b4026886 Mon Sep 17 00:00:00 2001 From: Stefan Date: Thu, 4 Jul 2024 12:29:58 +0200 Subject: [PATCH 1/2] feat: customizable fn timeout --- bindings/nodejs/index.d.ts | 1 + bindings/nodejs/src/config.rs | 9 ++++++++- core/engine/src/config.rs | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/bindings/nodejs/index.d.ts b/bindings/nodejs/index.d.ts index bd101ac0..6ef6ae82 100644 --- a/bindings/nodejs/index.d.ts +++ b/bindings/nodejs/index.d.ts @@ -5,6 +5,7 @@ export interface ZenConfig { nodesInContext?: boolean + functionTimeout?: number } export function overrideConfig(config: ZenConfig): void export interface ZenEvaluateOptions { diff --git a/bindings/nodejs/src/config.rs b/bindings/nodejs/src/config.rs index b96a52c9..89d51e16 100644 --- a/bindings/nodejs/src/config.rs +++ b/bindings/nodejs/src/config.rs @@ -5,12 +5,19 @@ use zen_engine::ZEN_CONFIG; #[napi(object)] pub struct ZenConfig { pub nodes_in_context: Option, + pub function_timeout: Option, } #[allow(dead_code)] #[napi] pub fn override_config(config: ZenConfig) { if let Some(val) = config.nodes_in_context { - ZEN_CONFIG.nodes_in_context.store(val, Ordering::Relaxed) + ZEN_CONFIG.nodes_in_context.store(val, Ordering::Relaxed); + } + + if let Some(val) = config.function_timeout { + ZEN_CONFIG + .function_timeout + .store(val as u64, Ordering::Relaxed); } } diff --git a/core/engine/src/config.rs b/core/engine/src/config.rs index 3d104844..3b349cec 100644 --- a/core/engine/src/config.rs +++ b/core/engine/src/config.rs @@ -1,15 +1,19 @@ +use std::sync::atomic::{AtomicBool, AtomicU64}; + use once_cell::sync::Lazy; -use std::sync::atomic::AtomicBool; #[derive(Debug)] pub struct ZenConfig { pub nodes_in_context: AtomicBool, + /// Function timeout presented in millis + pub function_timeout: AtomicU64, } impl Default for ZenConfig { fn default() -> Self { Self { nodes_in_context: AtomicBool::new(true), + function_timeout: AtomicU64::new(500), } } } From e9e7662fa51cb029ab01b0b9590094ac56b38476 Mon Sep 17 00:00:00 2001 From: Stefan Date: Thu, 24 Oct 2024 18:13:07 +0200 Subject: [PATCH 2/2] rebase --- core/engine/src/config.rs | 2 +- core/engine/src/handler/function/mod.rs | 12 +++++++++--- core/engine/src/handler/function_v1/mod.rs | 16 ++++++++++++---- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/core/engine/src/config.rs b/core/engine/src/config.rs index 3b349cec..0c67c131 100644 --- a/core/engine/src/config.rs +++ b/core/engine/src/config.rs @@ -13,7 +13,7 @@ impl Default for ZenConfig { fn default() -> Self { Self { nodes_in_context: AtomicBool::new(true), - function_timeout: AtomicU64::new(500), + function_timeout: AtomicU64::new(5_000), } } } diff --git a/core/engine/src/handler/function/mod.rs b/core/engine/src/handler/function/mod.rs index e98519ea..df50bb16 100644 --- a/core/engine/src/handler/function/mod.rs +++ b/core/engine/src/handler/function/mod.rs @@ -1,4 +1,5 @@ use std::rc::Rc; +use std::sync::atomic::Ordering; use std::time::Duration; use ::serde::{Deserialize, Serialize}; @@ -11,6 +12,7 @@ use crate::handler::function::function::{Function, HandlerResponse}; use crate::handler::function::serde::JsValue; use crate::handler::node::{NodeRequest, NodeResponse, NodeResult}; use crate::model::{DecisionNodeKind, FunctionNodeContent}; +use crate::ZEN_CONFIG; pub(crate) mod error; pub(crate) mod function; @@ -29,17 +31,19 @@ pub struct FunctionHandler { trace: bool, iteration: u8, max_depth: u8, + max_duration: Duration, } -static MAX_DURATION: Duration = Duration::from_millis(5_000); - impl FunctionHandler { pub fn new(function: Rc, trace: bool, iteration: u8, max_depth: u8) -> Self { + let max_duration_millis = ZEN_CONFIG.function_timeout.load(Ordering::Relaxed); + Self { function, trace, iteration, max_depth, + max_duration: Duration::from_millis(max_duration_millis), } } @@ -56,7 +60,9 @@ impl FunctionHandler { let module_name = self .function .suggest_module_name(request.node.id.as_str(), request.node.name.as_str()); - let interrupt_handler = Box::new(move || start.elapsed() > MAX_DURATION); + + let max_duration = self.max_duration.clone(); + let interrupt_handler = Box::new(move || start.elapsed() > max_duration); self.function .runtime() .set_interrupt_handler(Some(interrupt_handler)) diff --git a/core/engine/src/handler/function_v1/mod.rs b/core/engine/src/handler/function_v1/mod.rs index 1dde7059..95848c90 100644 --- a/core/engine/src/handler/function_v1/mod.rs +++ b/core/engine/src/handler/function_v1/mod.rs @@ -1,8 +1,10 @@ +use std::sync::atomic::Ordering; use std::time::{Duration, Instant}; use crate::handler::function_v1::script::Script; use crate::handler::node::{NodeRequest, NodeResponse, NodeResult}; use crate::model::{DecisionNodeKind, FunctionNodeContent}; +use crate::ZEN_CONFIG; use anyhow::anyhow; use rquickjs::Runtime; use serde_json::json; @@ -13,13 +15,18 @@ mod script; pub struct FunctionHandler { trace: bool, runtime: Runtime, + max_duration: Duration, } -static MAX_DURATION: Duration = Duration::from_millis(500); - impl FunctionHandler { pub fn new(trace: bool, runtime: Runtime) -> Self { - Self { trace, runtime } + let max_duration_millis = ZEN_CONFIG.function_timeout.load(Ordering::Relaxed); + + Self { + trace, + runtime, + max_duration: Duration::from_millis(max_duration_millis), + } } pub async fn handle(&self, request: NodeRequest) -> NodeResult { @@ -32,7 +39,8 @@ impl FunctionHandler { }?; let start = Instant::now(); - let interrupt_handler = Box::new(move || start.elapsed() > MAX_DURATION); + let max_duration = self.max_duration.clone(); + let interrupt_handler = Box::new(move || start.elapsed() > max_duration); self.runtime.set_interrupt_handler(Some(interrupt_handler)); let mut script = Script::new(self.runtime.clone());