use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum StorageTier {
Hot,
Warm,
Cold,
}
impl StorageTier {
pub fn typical_latency(&self) -> Duration {
match self {
StorageTier::Hot => Duration::from_micros(100), StorageTier::Warm => Duration::from_millis(5), StorageTier::Cold => Duration::from_millis(100), }
}
pub fn cost_factor(&self) -> f64 {
match self {
StorageTier::Hot => 10.0, StorageTier::Warm => 2.0, StorageTier::Cold => 1.0, }
}
pub fn compression_ratio(&self) -> f64 {
match self {
StorageTier::Hot => 1.0, StorageTier::Warm => 1.2, StorageTier::Cold => 4.0, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IndexMetadata {
pub index_id: String,
pub current_tier: StorageTier,
pub size_bytes: u64,
pub compressed_size_bytes: u64,
pub vector_count: usize,
pub dimension: usize,
pub index_type: IndexType,
pub created_at: SystemTime,
pub last_accessed: SystemTime,
pub last_modified: SystemTime,
pub access_stats: AccessStatistics,
pub performance_metrics: PerformanceMetrics,
pub storage_path: Option<PathBuf>,
pub custom_metadata: HashMap<String, String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum IndexType {
Hnsw,
Ivf,
Pq,
Sq,
Lsh,
Nsg,
Flat,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct AccessStatistics {
pub total_queries: u64,
pub queries_last_hour: u64,
pub queries_last_day: u64,
pub queries_last_week: u64,
pub avg_qps: f64,
pub peak_qps: f64,
pub last_access_time: Option<SystemTime>,
pub access_pattern: AccessPattern,
pub query_latencies: LatencyPercentiles,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum AccessPattern {
Hot,
Warm,
Cold,
Bursty,
Seasonal,
#[default]
Unknown,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct LatencyPercentiles {
pub p50: u64,
pub p95: u64,
pub p99: u64,
pub max: u64,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PerformanceMetrics {
pub avg_query_latency_us: u64,
pub avg_load_time_ms: u64,
pub cache_hit_rate: f64,
pub memory_footprint_bytes: u64,
pub cpu_utilization: f64,
pub iops: f64,
pub throughput_mbps: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TierStatistics {
pub capacity_bytes: u64,
pub used_bytes: u64,
pub index_count: usize,
pub total_queries: u64,
pub avg_query_latency_us: u64,
pub hit_rate: f64,
pub promotions: u64,
pub demotions: u64,
pub bytes_read: u64,
pub bytes_written: u64,
pub last_updated: SystemTime,
}
impl Default for TierStatistics {
fn default() -> Self {
Self {
capacity_bytes: 0,
used_bytes: 0,
index_count: 0,
total_queries: 0,
avg_query_latency_us: 0,
hit_rate: 0.0,
promotions: 0,
demotions: 0,
bytes_read: 0,
bytes_written: 0,
last_updated: SystemTime::now(),
}
}
}
impl TierStatistics {
pub fn utilization(&self) -> f64 {
if self.capacity_bytes == 0 {
0.0
} else {
self.used_bytes as f64 / self.capacity_bytes as f64
}
}
pub fn available_bytes(&self) -> u64 {
self.capacity_bytes.saturating_sub(self.used_bytes)
}
pub fn is_near_capacity(&self, threshold: f64) -> bool {
self.utilization() >= threshold
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TierTransition {
pub index_id: String,
pub from_tier: StorageTier,
pub to_tier: StorageTier,
pub reason: String,
pub timestamp: SystemTime,
pub duration: Duration,
pub success: bool,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GradualTransitionConfig {
pub enabled: bool,
pub stages: usize,
pub stage_delay: Duration,
pub monitor_performance: bool,
pub rollback_on_degradation: bool,
pub degradation_threshold: f64,
}
impl Default for GradualTransitionConfig {
fn default() -> Self {
Self {
enabled: true,
stages: 3,
stage_delay: Duration::from_secs(60),
monitor_performance: true,
rollback_on_degradation: true,
degradation_threshold: 0.2, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TierCostModel {
pub hot_cost_per_gb_hour: f64,
pub warm_cost_per_gb_hour: f64,
pub cold_cost_per_gb_hour: f64,
pub hot_query_cost: f64,
pub warm_query_cost: f64,
pub cold_query_cost: f64,
pub transition_cost: f64,
}
impl Default for TierCostModel {
fn default() -> Self {
Self {
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, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TenantResourceAllocation {
pub tenant_id: String,
pub hot_tier_allocation_bytes: u64,
pub warm_tier_allocation_bytes: u64,
pub cold_tier_allocation_bytes: u64,
pub qps_quota: f64,
pub priority: u32,
pub custom_policies: HashMap<String, String>,
}