use sqlx::PgPool; use tokio::sync::broadcast; use crate::config::AppConfig; use crate::services::compression::CompressionWorker; use crate::services::rate_limiter::RateLimiter; use crate::services::sse_tickets::SseTicketStore; #[derive(Clone, Debug)] pub struct SseEvent { pub event_type: String, pub data: String, } impl SseEvent { /// Standardised constructor. Prefer this over building the struct inline so the /// event-type strings stay consistent across handlers. pub fn new(event_type: impl Into, data: impl Into) -> Self { Self { event_type: event_type.into(), data: data.into(), } } } #[derive(Clone)] pub struct AppState { pub pool: PgPool, pub config: AppConfig, pub sse_tx: broadcast::Sender, pub compression: CompressionWorker, pub rate_limiter: RateLimiter, pub sse_tickets: SseTicketStore, } impl AppState { pub fn new(pool: PgPool, config: AppConfig) -> Self { let (sse_tx, _) = broadcast::channel(256); let compression = CompressionWorker::new(pool.clone(), config.media_path.clone(), 2, sse_tx.clone()); Self { pool, config, sse_tx, compression, rate_limiter: RateLimiter::new(), sse_tickets: SseTicketStore::new(), } } }