feat: cap queued jobs per concurrency key on cloud (#10197)

* feat: cap queued jobs per concurrency key on cloud

* fix: close preprocessed-flow bypass and bound concurrency cap scan

* fix: only cap concurrency keys with an active concurrent_limit

* chore: only load concurrency key cap setting when cloud hosted

* fix: reject queued-job import on cloud
This commit is contained in:
Ruben Fiszel
2026-07-20 12:33:40 +02:00
committed by GitHub
parent 1abfe49f7e
commit 71f2d47cb4
17 changed files with 446 additions and 45 deletions
@@ -116,6 +116,11 @@ pub const WORKSPACE_FAIRNESS_MAX_PERCENT_SETTING: &str = "workspace_fairness_max
pub const WORKSPACE_FAIRNESS_DURATION_SECS_SETTING: &str = "workspace_fairness_duration_secs";
pub const WORKSPACE_FAIRNESS_MIN_TOTAL_SETTING: &str = "workspace_fairness_min_total_jobs";
// Cloud-only ceiling on how many jobs may sit in the queue behind a single
// concurrency key. `0` disables the cap. See `windmill-queue/src/jobs.rs`,
// `check_concurrency_key_queue_cap`.
pub const CONCURRENCY_KEY_MAX_QUEUED_SETTING: &str = "concurrency_key_max_queued_jobs";
/// Global settings an agent worker (a remote worker connected over HTTP instead
/// of to the database) must NEVER read through
/// `GET /api/agent_workers/get_global_setting/{key}`. Every other key is served.
+10
View File
@@ -210,6 +210,9 @@ impl SpecificTagType {
pub const DEFAULT_CLOUD_TIMEOUT: u64 = 900;
pub const DEFAULT_SELFHOSTED_TIMEOUT: u64 = 604800; // 7 days
pub const MIN_PERIODIC_SCRIPT_INTERVAL_SECONDS: u64 = 60;
/// Default for [`CONCURRENCY_KEY_MAX_QUEUED`]; also the value the setting loader restores when
/// the setting is cleared or malformed.
pub const CONCURRENCY_KEY_MAX_QUEUED_DEFAULT: u32 = 10_000;
lazy_static::lazy_static! {
pub static ref WORKER_GROUP: String = std::env::var("WORKER_GROUP").unwrap_or_else(|_| {
#[cfg(not(feature = "enterprise"))]
@@ -337,6 +340,13 @@ lazy_static::lazy_static! {
/// `should_admit_capped` is moot and "admit all" is the correct no-op.
pub static ref WORKSPACE_FAIRNESS_ADMISSION_PPM: AtomicU32 = AtomicU32::new(10_000);
/// Cloud-only ceiling on the number of jobs queued behind a single concurrency key.
/// A concurrency-limited key drains at most `concurrent_limit` jobs per window, so a
/// producer pushing faster than that grows an unbounded backlog that no amount of
/// spare worker capacity can absorb. `0` disables the cap.
pub static ref CONCURRENCY_KEY_MAX_QUEUED: AtomicU32 =
AtomicU32::new(CONCURRENCY_KEY_MAX_QUEUED_DEFAULT);
pub static ref SMTP_CONFIG: arc_swap::ArcSwap<Option<Smtp>> = arc_swap::ArcSwap::from_pointee(None);
pub static ref INDEXER_CONFIG: arc_swap::ArcSwap<TantivyIndexerSettings> = arc_swap::ArcSwap::from_pointee(TantivyIndexerSettings::default());