Files
windmill/backend/windmill-api/src/public_app_rate_limit.rs
T
hugocasaandClaude Opus 5 98bacab907 refactor: combine the per-minute counters onto one shared helper (#10687)
* refactor: combine the per-minute counters onto one shared helper

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: keep dashmap in windmill-store for the azure devops token cache

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor: name the sweep counter for what it counts

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 18:45:20 +02:00

33 lines
1.1 KiB
Rust

/*
* Author: Windmill Labs, Inc
* Copyright: Windmill Labs, Inc 2024
* This file and its contents are licensed under the AGPLv3 License.
* Please see the included NOTICE for copyright information and
* LICENSE-AGPL for a copy of the license.
*/
use hyper::StatusCode;
use std::sync::LazyLock;
use windmill_common::error::{Error, Result};
use windmill_common::per_minute_counter::PerMinuteCounter;
static RATE_LIMIT_COUNTER: LazyLock<PerMinuteCounter<String>> =
LazyLock::new(PerMinuteCounter::new);
pub fn check_and_increment(workspace_id: &str, limit: i32) -> Result<()> {
// Clamp before the cast: `as u32` on a negative limit wraps into an effectively unlimited
// allowance, where a non-positive limit must reject every execution.
if RATE_LIMIT_COUNTER.try_increment(workspace_id.to_string(), limit.max(0) as u32) {
return Ok(());
}
Err(Error::Generic(
StatusCode::TOO_MANY_REQUESTS,
format!(
"Rate limit exceeded for public app executions in workspace '{}'. \
Limit: {} per minute per server.",
workspace_id, limit
),
))
}