brewlog/src/application/routes/api/stats.rs
Jon Seager 97c00f2e33
feat(stats): add pre-computed stats cache with background recomputation
- Add CachedStats domain types (roast summary, consumption, brewing)
- Extend StatsRepository with summary queries and cache get/store
- Add StatsInvalidator + background task with 2s debounce
- Add invalidate() calls to all entity create/update/delete handlers
- Add POST /api/v1/stats/recompute endpoint for manual refresh
- Add stats_cache migration and include in database reset
- Add GeoStats::from_counts() and Serialize/Deserialize derives
- Add 6 integration tests for stats API
- Document Stats Cache pattern in CLAUDE.md
2026-02-08 15:20:01 +00:00

27 lines
800 B
Rust

use axum::Json;
use axum::extract::State;
use crate::application::auth::AuthenticatedUser;
use crate::application::errors::{ApiError, AppError};
use crate::application::services::stats::compute_all_stats;
use crate::application::state::AppState;
use crate::domain::stats::CachedStats;
/// Force an immediate stats recomputation, bypassing the debounce timer.
#[tracing::instrument(skip(state, _auth_user))]
pub(crate) async fn recompute_stats(
State(state): State<AppState>,
_auth_user: AuthenticatedUser,
) -> Result<Json<CachedStats>, ApiError> {
let cached = compute_all_stats(&*state.stats_repo)
.await
.map_err(AppError::from)?;
state
.stats_repo
.store_cached(&cached)
.await
.map_err(AppError::from)?;
Ok(Json(cached))
}