| name | rate-limiting |
| description | Use when working with per-model daily request counters, rate limit errors, the America/Los_Angeles reset logic, or RPD quota enforcement. |
Rate Limiting Design
Overview
rs-summarizer implements per-model daily request counters to prevent exceeding Gemini API quotas. Counters reset at the start of each calendar day in America/Los_Angeles timezone.
Architecture
Rate limiting state lives in AppState (shared across all requests):
pub struct AppState {
pub model_counts: Arc<RwLock<HashMap<String, u32>>>,
pub last_reset_day: Arc<RwLock<Option<NaiveDate>>>,
}
RateLimiter API
File: src/services/rate_limiter.rs
pub struct RateLimiter;
impl RateLimiter {
pub async fn check_rate_limit(
model: &ModelOption,
model_counts: &Arc<RwLock<HashMap<String, u32>>>,
last_reset_day: &Arc<RwLock<Option<NaiveDate>>>,
) -> bool;
pub async fn increment_counter(
model_name: &str,
model_counts: &Arc<RwLock<HashMap<String, u32>>>,
);
}
Daily Reset Logic
maybe_reset_counters() is called on every check_rate_limit():
- Compute today's date in America/Los_Angeles (approximated as UTC-8)
- Compare with
last_reset_day
- If different day (or first run): clear all counters, update
last_reset_day
- If same day: no-op
fn today_la() -> NaiveDate {
let utc_now = chrono::Utc::now();
let la_time = utc_now - chrono::Duration::hours(8);
la_time.date_naive()
}
Note: Uses fixed UTC-8 offset (PST approximation). For DST-aware handling, chrono-tz could be added.
Usage in Route Handler
let allowed = RateLimiter::check_rate_limit(&model, &app.model_counts, &app.last_reset_day).await;
if !allowed {
return Html("<p>Rate limit exceeded...</p>".to_string());
}
RateLimiter::increment_counter(&input.model, &app.model_counts).await;
Model Limits
Each ModelOption has rpd_limit (requests per day). The counter is compared against this:
let current_count = counts.get(&model.name).copied().unwrap_or(0);
current_count < model.rpd_limit
Relevant Files
src/services/rate_limiter.rs โ Rate limiter implementation
src/state.rs โ ModelOption.rpd_limit field
src/routes/mod.rs โ Check + increment in process_transcript()
Browser Test
test_rate_limit_error_display (port 4453) verifies the rate limit UI end-to-end: creates a model with rpd_limit=1, submits once (exhausts limit), submits again, and asserts "Rate limit exceeded" is shown with no polling partial. Run with: cargo test --test integration_browser test_rate_limit_error_display -- --ignored