#[cfg(feature = "api-server")]
use crate::{CacheManager, EmbeddingModel, ModelRegistry};
use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::RwLock;
use uuid::Uuid;
#[derive(Debug, Default)]
pub struct ApiMetrics {
total_requests: AtomicU64,
total_errors: AtomicU64,
total_latency_us: AtomicU64,
}
impl ApiMetrics {
pub fn new() -> Self {
Self::default()
}
pub fn record(&self, latency: Duration, is_error: bool) {
self.total_requests.fetch_add(1, Ordering::Relaxed);
if is_error {
self.total_errors.fetch_add(1, Ordering::Relaxed);
}
let micros = latency.as_micros().min(u128::from(u64::MAX)) as u64;
self.total_latency_us.fetch_add(micros, Ordering::Relaxed);
}
pub fn total_requests(&self) -> u64 {
self.total_requests.load(Ordering::Relaxed)
}
pub fn avg_response_time_ms(&self) -> f64 {
let requests = self.total_requests.load(Ordering::Relaxed);
if requests == 0 {
return 0.0;
}
let total_us = self.total_latency_us.load(Ordering::Relaxed) as f64;
(total_us / requests as f64) / 1000.0
}
pub fn error_rate_percent(&self) -> f64 {
let requests = self.total_requests.load(Ordering::Relaxed);
if requests == 0 {
return 0.0;
}
let errors = self.total_errors.load(Ordering::Relaxed) as f64;
(errors / requests as f64) * 100.0
}
}
#[derive(Clone)]
pub struct ApiState {
pub registry: Arc<ModelRegistry>,
pub cache_manager: Arc<CacheManager>,
pub models: Arc<RwLock<HashMap<Uuid, Arc<dyn EmbeddingModel + Send + Sync>>>>,
pub metrics: Arc<ApiMetrics>,
pub config: ApiConfig,
}
#[derive(Debug, Clone)]
pub struct ApiConfig {
pub host: String,
pub port: u16,
pub timeout_seconds: u64,
pub request_timeout_secs: u64,
pub max_batch_size: usize,
pub rate_limit: RateLimitConfig,
pub auth: AuthConfig,
pub enable_logging: bool,
pub enable_cors: bool,
}
impl Default for ApiConfig {
fn default() -> Self {
Self {
host: "0.0.0.0".to_string(),
port: 8080,
timeout_seconds: 30,
request_timeout_secs: 30,
max_batch_size: 1000,
rate_limit: RateLimitConfig::default(),
auth: AuthConfig::default(),
enable_logging: true,
enable_cors: true,
}
}
}
#[derive(Debug, Clone)]
pub struct RateLimitConfig {
pub requests_per_minute: u32,
pub enabled: bool,
}
impl Default for RateLimitConfig {
fn default() -> Self {
Self {
requests_per_minute: 1000,
enabled: true,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct AuthConfig {
pub require_api_key: bool,
pub api_keys: Vec<String>,
pub enable_jwt: bool,
pub jwt_secret: Option<String>,
}