diff --git a/backend/windmill-jseval/src/lib.rs b/backend/windmill-jseval/src/lib.rs index 4b6bd20be1..bb0f27ee2b 100644 --- a/backend/windmill-jseval/src/lib.rs +++ b/backend/windmill-jseval/src/lib.rs @@ -19,6 +19,8 @@ use std::collections::HashMap; use std::sync::Arc; +pub const EVAL_TIMEOUT_MS: u64 = 20000; + use lazy_static::lazy_static; use regex::Regex; #[cfg(feature = "quickjs")] @@ -274,7 +276,7 @@ pub async fn eval_timeout_quickjs( // Run the QuickJS evaluation with a timeout tokio::time::timeout( - std::time::Duration::from_millis(10000), + std::time::Duration::from_millis(EVAL_TIMEOUT_MS), tokio::task::spawn_blocking(move || { // Create a new tokio runtime for async operations within the blocking context let rt = tokio::runtime::Builder::new_current_thread() @@ -298,7 +300,7 @@ pub async fn eval_timeout_quickjs( ) .await .map_err(|_| { - anyhow::anyhow!("The expression evaluation `{expr}` took too long to execute (>10000ms)") + anyhow::anyhow!("The expression evaluation `{expr}` took too long to execute (>{EVAL_TIMEOUT_MS}ms)") })?? } @@ -786,7 +788,7 @@ pub async fn eval_simple_js( globals: HashMap, ) -> anyhow::Result> { tokio::time::timeout( - std::time::Duration::from_millis(10000), + std::time::Duration::from_millis(EVAL_TIMEOUT_MS), tokio::task::spawn_blocking(move || { let rt = tokio::runtime::Builder::new_current_thread() .enable_all() @@ -819,7 +821,7 @@ pub async fn eval_simple_js( ) .await .map_err(|_| { - anyhow::anyhow!("The expression evaluation took too long to execute (>10000ms)") + anyhow::anyhow!("The expression evaluation took too long to execute (>{EVAL_TIMEOUT_MS}ms)") })?? } diff --git a/backend/windmill-worker/src/js_eval.rs b/backend/windmill-worker/src/js_eval.rs index 5ee3b34cf9..bc8b33a5f2 100644 --- a/backend/windmill-worker/src/js_eval.rs +++ b/backend/windmill-worker/src/js_eval.rs @@ -78,16 +78,33 @@ pub async fn eval_timeout( } } - windmill_jseval::eval_timeout_quickjs( - expr, - transform_context, - flow_input, - flow_env, - authed_client, - by_id, - ctx, - ) - .await + let mut attempts = 0; + loop { + let result = windmill_jseval::eval_timeout_quickjs( + expr.clone(), + transform_context.clone(), + flow_input.clone(), + flow_env, + authed_client, + by_id, + ctx.clone(), + ) + .await; + + match result { + Ok(v) => return Ok(v), + Err(e) if attempts < 2 && e.to_string().contains("took too long") => { + attempts += 1; + tracing::warn!( + "js eval timed out (attempt {}/3), retrying in 5s: {}", + attempts, + expr + ); + tokio::time::sleep(std::time::Duration::from_secs(5)).await; + } + Err(e) => return Err(e), + } + } } #[cfg(feature = "deno_core")]