use arc_swap::ArcSwap;
use crabllm_core::{Extension, GatewayConfig, Provider, Storage};
use crabllm_provider::ProviderRegistry;
use std::{
collections::HashMap,
sync::{Arc, RwLock},
time::SystemTime,
};
use tokio::sync::broadcast;
#[derive(Debug, Clone)]
pub struct UsageEvent {
pub timestamp: SystemTime,
pub request_id: String,
pub principal: Option<String>,
pub model: String,
pub provider: String,
pub endpoint: &'static str,
pub tokens_in: u32,
pub tokens_out: u32,
pub duration_ms: u64,
pub status: u16,
pub error: Option<String>,
}
pub struct AppState<S: Storage, P: Provider> {
pub registry: Arc<ArcSwap<ProviderRegistry<P>>>,
pub config: GatewayConfig,
pub extensions: Arc<Vec<Box<dyn Extension>>>,
pub storage: Arc<S>,
pub key_map: Arc<RwLock<HashMap<String, String>>>,
pub usage_events: Option<broadcast::Sender<UsageEvent>>,
}
impl<S: Storage, P: Provider> Clone for AppState<S, P> {
fn clone(&self) -> Self {
Self {
registry: self.registry.clone(),
config: self.config.clone(),
extensions: self.extensions.clone(),
storage: self.storage.clone(),
key_map: self.key_map.clone(),
usage_events: self.usage_events.clone(),
}
}
}
impl<S: Storage, P: Provider> AppState<S, P> {
pub fn registry(&self) -> arc_swap::Guard<Arc<ProviderRegistry<P>>> {
self.registry.load()
}
}