From 946848feef60aba2a54bc2f5b686b33cc96ec9ef Mon Sep 17 00:00:00 2001 From: hugocasa Date: Fri, 10 Apr 2026 16:35:13 +0200 Subject: [PATCH] fix: limit multi-runnable dedicated workers to one job at a time (#8782) * feat: thread concurrency semaphore through dedicated worker executors Pass the concurrency_semaphore parameter through bun, deno, and python start_worker functions to handle_dedicated_process. Also fix the DedicatedWorkersSelector to use listWorkspacesAsSuperAdmin (so all workspaces including admins are visible) and skip loading when disabled. Co-Authored-By: Claude Opus 4.6 (1M context) * chore: update ee-repo-ref to limit-workers-one-job branch Co-Authored-By: Claude Opus 4.6 (1M context) * chore: update ee-repo-ref to 54037e77cdd37777560755fef7075d35906c96d8 This commit updates the EE repository reference after PR #523 was merged in windmill-ee-private. Previous ee-repo-ref: 56890ea8fca2c1c44a1338a27011b4dd1137d9c9 New ee-repo-ref: 54037e77cdd37777560755fef7075d35906c96d8 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.6 (1M context) Co-authored-by: windmill-internal-app[bot] Co-authored-by: Ruben Fiszel --- backend/ee-repo-ref.txt | 2 +- backend/windmill-worker/src/bun_executor.rs | 3 +++ backend/windmill-worker/src/deno_executor.rs | 2 ++ backend/windmill-worker/src/python_executor.rs | 2 ++ frontend/src/lib/components/DedicatedWorkersSelector.svelte | 6 ++++-- 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index 5ee5e38328..5dd4cbc7f7 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -bcfb663f9e902539abbbf69c517715eb8d4ce8f9 +54037e77cdd37777560755fef7075d35906c96d8 diff --git a/backend/windmill-worker/src/bun_executor.rs b/backend/windmill-worker/src/bun_executor.rs index 7e2d85f745..842d2c6659 100644 --- a/backend/windmill-worker/src/bun_executor.rs +++ b/backend/windmill-worker/src/bun_executor.rs @@ -3574,6 +3574,7 @@ pub async fn start_worker( jobs_rx: Receiver, killpill_rx: tokio::sync::broadcast::Receiver<()>, client: windmill_common::client::AuthedClient, + concurrency_semaphore: Option>, ) -> Result<()> { let mut logs = "".to_string(); let mut mem_peak: i32 = 0; @@ -3841,6 +3842,7 @@ pub async fn start_worker( "nodejs", client, false, + concurrency_semaphore, ) .await } else { @@ -3869,6 +3871,7 @@ pub async fn start_worker( "bun", client, false, + concurrency_semaphore, ) .await } diff --git a/backend/windmill-worker/src/deno_executor.rs b/backend/windmill-worker/src/deno_executor.rs index e48a6028ef..3cc9a5ba1d 100644 --- a/backend/windmill-worker/src/deno_executor.rs +++ b/backend/windmill-worker/src/deno_executor.rs @@ -722,6 +722,7 @@ pub async fn start_worker( killpill_rx: tokio::sync::broadcast::Receiver<()>, db: &sqlx::Pool, client: windmill_common::client::AuthedClient, + concurrency_semaphore: Option>, ) -> Result<()> { use windmill_common::variables; @@ -791,6 +792,7 @@ pub async fn start_worker( "deno", client, false, + concurrency_semaphore, ) .await } diff --git a/backend/windmill-worker/src/python_executor.rs b/backend/windmill-worker/src/python_executor.rs index 453b4e986c..de8a38effb 100644 --- a/backend/windmill-worker/src/python_executor.rs +++ b/backend/windmill-worker/src/python_executor.rs @@ -2780,6 +2780,7 @@ pub async fn start_worker( jobs_rx: tokio::sync::mpsc::Receiver, killpill_rx: tokio::sync::broadcast::Receiver<()>, client: windmill_common::client::AuthedClient, + concurrency_semaphore: Option>, ) -> error::Result<()> { use crate::PyV; tracing::info!("script path: {}", script_path); @@ -2922,6 +2923,7 @@ pub async fn start_worker( "python", client, false, + concurrency_semaphore, ) .await } diff --git a/frontend/src/lib/components/DedicatedWorkersSelector.svelte b/frontend/src/lib/components/DedicatedWorkersSelector.svelte index 670e0384bd..d318faf9e5 100644 --- a/frontend/src/lib/components/DedicatedWorkersSelector.svelte +++ b/frontend/src/lib/components/DedicatedWorkersSelector.svelte @@ -307,13 +307,15 @@ }) $effect(() => { - loadWorkspaces() + if (!disabled) { + loadWorkspaces() + } }) async function loadWorkspaces() { try { workspacesLoading = true - const ws = await WorkspaceService.listWorkspaces() + const ws = await WorkspaceService.listWorkspacesAsSuperAdmin() workspaces = ws.map((w) => ({ id: w.id, name: w.name })) } catch (e) { console.error('Failed to load workspaces', e)