oxirs_embed/api/
config.rs1#[cfg(feature = "api-server")]
7use crate::{CacheManager, EmbeddingModel, ModelRegistry};
8use std::collections::HashMap;
9use std::sync::atomic::{AtomicU64, Ordering};
10use std::sync::Arc;
11use std::time::Duration;
12use tokio::sync::RwLock;
13use uuid::Uuid;
14
15#[derive(Debug, Default)]
23pub struct ApiMetrics {
24 total_requests: AtomicU64,
25 total_errors: AtomicU64,
26 total_latency_us: AtomicU64,
27}
28
29impl ApiMetrics {
30 pub fn new() -> Self {
32 Self::default()
33 }
34
35 pub fn record(&self, latency: Duration, is_error: bool) {
37 self.total_requests.fetch_add(1, Ordering::Relaxed);
38 if is_error {
39 self.total_errors.fetch_add(1, Ordering::Relaxed);
40 }
41 let micros = latency.as_micros().min(u128::from(u64::MAX)) as u64;
43 self.total_latency_us.fetch_add(micros, Ordering::Relaxed);
44 }
45
46 pub fn total_requests(&self) -> u64 {
48 self.total_requests.load(Ordering::Relaxed)
49 }
50
51 pub fn avg_response_time_ms(&self) -> f64 {
53 let requests = self.total_requests.load(Ordering::Relaxed);
54 if requests == 0 {
55 return 0.0;
56 }
57 let total_us = self.total_latency_us.load(Ordering::Relaxed) as f64;
58 (total_us / requests as f64) / 1000.0
59 }
60
61 pub fn error_rate_percent(&self) -> f64 {
63 let requests = self.total_requests.load(Ordering::Relaxed);
64 if requests == 0 {
65 return 0.0;
66 }
67 let errors = self.total_errors.load(Ordering::Relaxed) as f64;
68 (errors / requests as f64) * 100.0
69 }
70}
71
72#[derive(Clone)]
74pub struct ApiState {
75 pub registry: Arc<ModelRegistry>,
77 pub cache_manager: Arc<CacheManager>,
79 pub models: Arc<RwLock<HashMap<Uuid, Arc<dyn EmbeddingModel + Send + Sync>>>>,
81 pub metrics: Arc<ApiMetrics>,
83 pub config: ApiConfig,
85}
86
87#[derive(Debug, Clone)]
89pub struct ApiConfig {
90 pub host: String,
92 pub port: u16,
94 pub timeout_seconds: u64,
96 pub request_timeout_secs: u64,
98 pub max_batch_size: usize,
100 pub rate_limit: RateLimitConfig,
102 pub auth: AuthConfig,
104 pub enable_logging: bool,
106 pub enable_cors: bool,
108}
109
110impl Default for ApiConfig {
111 fn default() -> Self {
112 Self {
113 host: "0.0.0.0".to_string(),
114 port: 8080,
115 timeout_seconds: 30,
116 request_timeout_secs: 30,
117 max_batch_size: 1000,
118 rate_limit: RateLimitConfig::default(),
119 auth: AuthConfig::default(),
120 enable_logging: true,
121 enable_cors: true,
122 }
123 }
124}
125
126#[derive(Debug, Clone)]
128pub struct RateLimitConfig {
129 pub requests_per_minute: u32,
131 pub enabled: bool,
133}
134
135impl Default for RateLimitConfig {
136 fn default() -> Self {
137 Self {
138 requests_per_minute: 1000,
139 enabled: true,
140 }
141 }
142}
143
144#[derive(Debug, Clone, Default)]
146pub struct AuthConfig {
147 pub require_api_key: bool,
149 pub api_keys: Vec<String>,
151 pub enable_jwt: bool,
153 pub jwt_secret: Option<String>,
155}