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, Default)]
118pub enum AccessPattern {
119 Hot,
121 Warm,
123 Cold,
125 Bursty,
127 Seasonal,
129 #[default]
131 Unknown,
132}
133
134#[derive(Debug, Clone, Default, Serialize, Deserialize)]
136pub struct LatencyPercentiles {
137 pub p50: u64,
138 pub p95: u64,
139 pub p99: u64,
140 pub max: u64,
141}
142
143#[derive(Debug, Clone, Default, Serialize, Deserialize)]
145pub struct PerformanceMetrics {
146 pub avg_query_latency_us: u64,
148 pub avg_load_time_ms: u64,
150 pub cache_hit_rate: f64,
152 pub memory_footprint_bytes: u64,
154 pub cpu_utilization: f64,
156 pub iops: f64,
158 pub throughput_mbps: f64,
160}
161
162#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct TierStatistics {
165 pub capacity_bytes: u64,
167 pub used_bytes: u64,
169 pub index_count: usize,
171 pub total_queries: u64,
173 pub avg_query_latency_us: u64,
175 pub hit_rate: f64,
177 pub promotions: u64,
179 pub demotions: u64,
181 pub bytes_read: u64,
183 pub bytes_written: u64,
185 pub last_updated: SystemTime,
187}
188
189impl Default for TierStatistics {
190 fn default() -> Self {
191 Self {
192 capacity_bytes: 0,
193 used_bytes: 0,
194 index_count: 0,
195 total_queries: 0,
196 avg_query_latency_us: 0,
197 hit_rate: 0.0,
198 promotions: 0,
199 demotions: 0,
200 bytes_read: 0,
201 bytes_written: 0,
202 last_updated: SystemTime::now(),
203 }
204 }
205}
206
207impl TierStatistics {
208 pub fn utilization(&self) -> f64 {
210 if self.capacity_bytes == 0 {
211 0.0
212 } else {
213 self.used_bytes as f64 / self.capacity_bytes as f64
214 }
215 }
216
217 pub fn available_bytes(&self) -> u64 {
219 self.capacity_bytes.saturating_sub(self.used_bytes)
220 }
221
222 pub fn is_near_capacity(&self, threshold: f64) -> bool {
224 self.utilization() >= threshold
225 }
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct TierTransition {
231 pub index_id: String,
233 pub from_tier: StorageTier,
235 pub to_tier: StorageTier,
237 pub reason: String,
239 pub timestamp: SystemTime,
241 pub duration: Duration,
243 pub success: bool,
245 pub error: Option<String>,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize)]
251pub struct GradualTransitionConfig {
252 pub enabled: bool,
254 pub stages: usize,
256 pub stage_delay: Duration,
258 pub monitor_performance: bool,
260 pub rollback_on_degradation: bool,
262 pub degradation_threshold: f64,
264}
265
266impl Default for GradualTransitionConfig {
267 fn default() -> Self {
268 Self {
269 enabled: true,
270 stages: 3,
271 stage_delay: Duration::from_secs(60),
272 monitor_performance: true,
273 rollback_on_degradation: true,
274 degradation_threshold: 0.2, }
276 }
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct TierCostModel {
282 pub hot_cost_per_gb_hour: f64,
284 pub warm_cost_per_gb_hour: f64,
286 pub cold_cost_per_gb_hour: f64,
288 pub hot_query_cost: f64,
290 pub warm_query_cost: f64,
292 pub cold_query_cost: f64,
294 pub transition_cost: f64,
296}
297
298impl Default for TierCostModel {
299 fn default() -> Self {
300 Self {
301 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, }
309 }
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct TenantResourceAllocation {
315 pub tenant_id: String,
317 pub hot_tier_allocation_bytes: u64,
319 pub warm_tier_allocation_bytes: u64,
321 pub cold_tier_allocation_bytes: u64,
323 pub qps_quota: f64,
325 pub priority: u32,
327 pub custom_policies: HashMap<String, String>,
329}