From b791ed75f3b5bb98f7776030bc726becfb20323f Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sun, 8 Feb 2026 02:13:00 +0300 Subject: [PATCH] fc-queue-runner: one-at-a-time jobset scheduling Signed-off-by: NotAShelf Change-Id: Iebe127bfba39979649826dfd0d28f9db6a6a6964 --- crates/queue-runner/src/runner_loop.rs | 53 +++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/crates/queue-runner/src/runner_loop.rs b/crates/queue-runner/src/runner_loop.rs index 9814253..99f51bc 100644 --- a/crates/queue-runner/src/runner_loop.rs +++ b/crates/queue-runner/src/runner_loop.rs @@ -1,6 +1,9 @@ use std::{sync::Arc, time::Duration}; -use fc_common::{models::BuildStatus, repo}; +use fc_common::{ + models::{BuildStatus, JobsetState}, + repo, +}; use sqlx::PgPool; use crate::worker::WorkerPool; @@ -117,6 +120,54 @@ pub async fn run( }, } + // One-at-a-time scheduling: check if jobset allows concurrent builds + // First, get the evaluation to find the jobset + let eval = + match repo::evaluations::get(&pool, build.evaluation_id).await { + Ok(eval) => eval, + Err(e) => { + tracing::error!( + build_id = %build.id, + evaluation_id = %build.evaluation_id, + "Failed to get evaluation for one-at-a-time check: {e}" + ); + continue; + }, + }; + + let jobset = match repo::jobsets::get(&pool, eval.jobset_id).await { + Ok(jobset) => jobset, + Err(e) => { + tracing::error!( + build_id = %build.id, + jobset_id = %eval.jobset_id, + "Failed to get jobset for one-at-a-time check: {e}" + ); + continue; + }, + }; + + if jobset.state == JobsetState::OneAtATime { + match repo::jobsets::has_running_builds(&pool, jobset.id).await { + Ok(true) => { + tracing::debug!( + build_id = %build.id, + jobset = %jobset.name, + "One-at-a-time: skipping, another build is running" + ); + continue; + }, + Ok(false) => {}, + Err(e) => { + tracing::error!( + build_id = %build.id, + "Failed to check running builds: {e}" + ); + continue; + }, + } + } + worker_pool.dispatch(build); } },