You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.7 KiB
Rust
96 lines
2.7 KiB
Rust
//! Database queries for the `admin_rate_limits` table.
|
|
//!
|
|
//! Provides read and upsert operations for per-provider rate limit configuration.
|
|
|
|
use sqlx::PgPool;
|
|
use uuid::Uuid;
|
|
|
|
use crate::errors::AppError;
|
|
use crate::models::rate_limit::AdminRateLimit;
|
|
|
|
/// Row type returned by sqlx queries against the `admin_rate_limits` table.
|
|
#[derive(Debug, sqlx::FromRow)]
|
|
struct RateLimitRow {
|
|
id: Uuid,
|
|
provider_name: String,
|
|
max_requests: i32,
|
|
time_window_seconds: i32,
|
|
updated_at: chrono::DateTime<chrono::Utc>,
|
|
}
|
|
|
|
impl From<RateLimitRow> for AdminRateLimit {
|
|
fn from(row: RateLimitRow) -> Self {
|
|
Self {
|
|
id: row.id,
|
|
provider_name: row.provider_name,
|
|
max_requests: row.max_requests,
|
|
time_window_seconds: row.time_window_seconds,
|
|
updated_at: row.updated_at,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// List all rate limit configurations.
|
|
pub async fn list_all(pool: &PgPool) -> Result<Vec<AdminRateLimit>, AppError> {
|
|
let rows = sqlx::query_as::<_, RateLimitRow>(
|
|
r#"
|
|
SELECT id, provider_name, max_requests, time_window_seconds, updated_at
|
|
FROM admin_rate_limits
|
|
ORDER BY provider_name
|
|
"#,
|
|
)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
Ok(rows.into_iter().map(AdminRateLimit::from).collect())
|
|
}
|
|
|
|
/// Get the rate limit configuration for a specific provider.
|
|
pub async fn get_by_provider(
|
|
pool: &PgPool,
|
|
provider_name: &str,
|
|
) -> Result<Option<AdminRateLimit>, AppError> {
|
|
let row = sqlx::query_as::<_, RateLimitRow>(
|
|
r#"
|
|
SELECT id, provider_name, max_requests, time_window_seconds, updated_at
|
|
FROM admin_rate_limits
|
|
WHERE provider_name = $1
|
|
"#,
|
|
)
|
|
.bind(provider_name)
|
|
.fetch_optional(pool)
|
|
.await?;
|
|
|
|
Ok(row.map(AdminRateLimit::from))
|
|
}
|
|
|
|
/// Upsert a rate limit configuration for a provider.
|
|
///
|
|
/// Creates the rate limit if it doesn't exist, or updates it if it does.
|
|
/// Returns the upserted rate limit.
|
|
pub async fn upsert(
|
|
pool: &PgPool,
|
|
provider_name: &str,
|
|
max_requests: i32,
|
|
time_window_seconds: i32,
|
|
) -> Result<AdminRateLimit, AppError> {
|
|
let row = sqlx::query_as::<_, RateLimitRow>(
|
|
r#"
|
|
INSERT INTO admin_rate_limits (provider_name, max_requests, time_window_seconds)
|
|
VALUES ($1, $2, $3)
|
|
ON CONFLICT (provider_name) DO UPDATE SET
|
|
max_requests = EXCLUDED.max_requests,
|
|
time_window_seconds = EXCLUDED.time_window_seconds,
|
|
updated_at = now()
|
|
RETURNING id, provider_name, max_requests, time_window_seconds, updated_at
|
|
"#,
|
|
)
|
|
.bind(provider_name)
|
|
.bind(max_requests)
|
|
.bind(time_window_seconds)
|
|
.fetch_one(pool)
|
|
.await?;
|
|
|
|
Ok(AdminRateLimit::from(row))
|
|
}
|