1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::path::PathBuf;
6use std::time::{Duration, SystemTime};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub enum StorageTier {
11 Hot,
13 Warm,
15 Cold,
17}
18
19impl StorageTier {
20 pub fn typical_latency(&self) -> Duration {
22 match self {
23 StorageTier::Hot => Duration::from_micros(100), StorageTier::Warm => Duration::from_millis(5), StorageTier::Cold => Duration::from_millis(100), }
27 }
28
29 pub fn cost_factor(&self) -> f64 {
31 match self {
32 StorageTier::Hot => 10.0, StorageTier::Warm => 2.0, StorageTier::Cold => 1.0, }
36 }
37
38 pub fn compression_ratio(&self) -> f64 {
40 match self {
41 StorageTier::Hot => 1.0, StorageTier::Warm => 1.2, StorageTier::Cold => 4.0, }
45 }
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct IndexMetadata {
51 pub index_id: String,
53 pub current_tier: StorageTier,
55 pub size_bytes: u64,
57 pub compressed_size_bytes: u64,
59 pub vector_count: usize,
61 pub dimension: usize,
63 pub index_type: IndexType,
65 pub created_at: SystemTime,
67 pub last_accessed: SystemTime,
69 pub last_modified: SystemTime,
71 pub access_stats: AccessStatistics,
73 pub performance_metrics: PerformanceMetrics,
75 pub storage_path: Option<PathBuf>,
77 pub custom_metadata: HashMap<String, String>,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
83pub enum IndexType {
84 Hnsw,
85 Ivf,
86 Pq,
87 Sq,
88 Lsh,
89 Nsg,
90 Flat,
91}
92
93#[derive(Debug, Clone, Default, Serialize, Deserialize)]
95pub struct AccessStatistics {
96 pub total_queries: u64,
98 pub queries_last_hour: u64,
100 pub queries_last_day: u64,
102 pub queries_last_week: u64,
104 pub avg_qps: f64,
106 pub peak_qps: f64,
108 pub last_access_time: Option<SystemTime>,
110 pub access_pattern: AccessPattern,
112 pub query_latencies: LatencyPercentiles,
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
118pub enum AccessPattern {
119 Hot,
121 Warm,
123 Cold,
125 Bursty,
127 Seasonal,
129 Unknown,
131}
132
133impl Default for AccessPattern {
134 fn default() -> Self {
135 Self::Unknown
136 }
137}
138
139#[derive(Debug, Clone, Default, Serialize, Deserialize)]
141pub struct LatencyPercentiles {
142 pub p50: u64,
143 pub p95: u64,
144 pub p99: u64,
145 pub max: u64,
146}
147
148#[derive(Debug, Clone, Default, Serialize, Deserialize)]
150pub struct PerformanceMetrics {
151 pub avg_query_latency_us: u64,
153 pub avg_load_time_ms: u64,
155 pub cache_hit_rate: f64,
157 pub memory_footprint_bytes: u64,
159 pub cpu_utilization: f64,
161 pub iops: f64,
163 pub throughput_mbps: f64,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct TierStatistics {
170 pub capacity_bytes: u64,
172 pub used_bytes: u64,
174 pub index_count: usize,
176 pub total_queries: u64,
178 pub avg_query_latency_us: u64,
180 pub hit_rate: f64,
182 pub promotions: u64,
184 pub demotions: u64,
186 pub bytes_read: u64,
188 pub bytes_written: u64,
190 pub last_updated: SystemTime,
192}
193
194impl Default for TierStatistics {
195 fn default() -> Self {
196 Self {
197 capacity_bytes: 0,
198 used_bytes: 0,
199 index_count: 0,
200 total_queries: 0,
201 avg_query_latency_us: 0,
202 hit_rate: 0.0,
203 promotions: 0,
204 demotions: 0,
205 bytes_read: 0,
206 bytes_written: 0,
207 last_updated: SystemTime::now(),
208 }
209 }
210}
211
212impl TierStatistics {
213 pub fn utilization(&self) -> f64 {
215 if self.capacity_bytes == 0 {
216 0.0
217 } else {
218 self.used_bytes as f64 / self.capacity_bytes as f64
219 }
220 }
221
222 pub fn available_bytes(&self) -> u64 {
224 self.capacity_bytes.saturating_sub(self.used_bytes)
225 }
226
227 pub fn is_near_capacity(&self, threshold: f64) -> bool {
229 self.utilization() >= threshold
230 }
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct TierTransition {
236 pub index_id: String,
238 pub from_tier: StorageTier,
240 pub to_tier: StorageTier,
242 pub reason: String,
244 pub timestamp: SystemTime,
246 pub duration: Duration,
248 pub success: bool,
250 pub error: Option<String>,
252}
253
254#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct GradualTransitionConfig {
257 pub enabled: bool,
259 pub stages: usize,
261 pub stage_delay: Duration,
263 pub monitor_performance: bool,
265 pub rollback_on_degradation: bool,
267 pub degradation_threshold: f64,
269}
270
271impl Default for GradualTransitionConfig {
272 fn default() -> Self {
273 Self {
274 enabled: true,
275 stages: 3,
276 stage_delay: Duration::from_secs(60),
277 monitor_performance: true,
278 rollback_on_degradation: true,
279 degradation_threshold: 0.2, }
281 }
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
286pub struct TierCostModel {
287 pub hot_cost_per_gb_hour: f64,
289 pub warm_cost_per_gb_hour: f64,
291 pub cold_cost_per_gb_hour: f64,
293 pub hot_query_cost: f64,
295 pub warm_query_cost: f64,
297 pub cold_query_cost: f64,
299 pub transition_cost: f64,
301}
302
303impl Default for TierCostModel {
304 fn default() -> Self {
305 Self {
306 hot_cost_per_gb_hour: 0.10, warm_cost_per_gb_hour: 0.02, cold_cost_per_gb_hour: 0.005, hot_query_cost: 0.0001, warm_query_cost: 0.0005, cold_query_cost: 0.002, transition_cost: 0.01, }
314 }
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct TenantResourceAllocation {
320 pub tenant_id: String,
322 pub hot_tier_allocation_bytes: u64,
324 pub warm_tier_allocation_bytes: u64,
326 pub cold_tier_allocation_bytes: u64,
328 pub qps_quota: f64,
330 pub priority: u32,
332 pub custom_policies: HashMap<String, String>,
334}