From 0258f3f81b96bb8d4e343ba8aeba614f9c836579 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Sat, 15 Aug 2026 16:43:51 +0200 Subject: [PATCH] perf: unblock workers before the API router is built (#10711) Co-authored-by: Claude Opus 5 (1M context) --- backend/src/main.rs | 4 ++++ backend/windmill-api/src/lib.rs | 15 ++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/backend/src/main.rs b/backend/src/main.rs index 6383bfd78e..2dff3209ac 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1629,6 +1629,10 @@ Windmill Community Edition {GIT_VERSION} } } + // `workers_f` must stay ahead of `server_f`: these are polled on one task in + // declaration order, and `run_server` yields once after handing over the base + // internal url so the workers get past that oneshot before it builds its router. + // Ordering `server_f` first makes them wait out the whole build instead. if mcp_mode { futures::try_join!(workers_f, server_f)?; } else { diff --git a/backend/windmill-api/src/lib.rs b/backend/windmill-api/src/lib.rs index 44d1d7cb2b..d2e0ea8e78 100644 --- a/backend/windmill-api/src/lib.rs +++ b/backend/windmill-api/src/lib.rs @@ -584,6 +584,16 @@ pub async fn run_server( (Router::new(), Router::new(), Option::<()>::None) }; + // Workers block on this before pulling their first job, so it is released ahead of + // the router tree below. `try_join!` polls this future and `workers_f` on one task, + // so the yield is what lets them proceed; without it they wait out the whole + // synchronous build. A request arriving first queues in the bound listener's backlog. + if let Err(e) = port_tx.send(format!("http://localhost:{}", port)) { + tracing::error!("Failed to send port: {e:#}"); + return Err(anyhow::anyhow!("Failed to send port, exiting early: {e:#}")); + } + tokio::task::yield_now().await; + let mcp_list_tools_service = { #[cfg(feature = "mcp")] { @@ -1181,11 +1191,6 @@ pub async fn run_server( name.map(|x| format!("name={x}")).unwrap_or_default() ); - if let Err(e) = port_tx.send(format!("http://localhost:{}", port)) { - tracing::error!("Failed to send port: {e:#}"); - return Err(anyhow::anyhow!("Failed to send port, exiting early: {e:#}")); - } - // Announce this server is ready so coordinated restarts can detect a healthy peer. if server_mode { if let Err(e) = announce_server_started(&db).await {