oxirs_vec/tiering/
config.rs

1//! Configuration for hot/warm/cold tiering system
2
3use super::policies::TieringPolicy;
4use super::types::{GradualTransitionConfig, TierCostModel};
5use serde::{Deserialize, Serialize};
6use std::path::PathBuf;
7use std::time::Duration;
8
9/// Main configuration for tiering system
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct TieringConfig {
12    /// Hot tier capacity in gigabytes
13    pub hot_tier_capacity_gb: f64,
14    /// Warm tier capacity in gigabytes
15    pub warm_tier_capacity_gb: f64,
16    /// Cold tier capacity in gigabytes
17    pub cold_tier_capacity_gb: f64,
18    /// Tiering policy
19    pub policy: TieringPolicy,
20    /// Base directory for storage
21    pub storage_base_path: PathBuf,
22    /// Enable automatic tier management
23    pub auto_tier_management: bool,
24    /// Tier evaluation interval
25    pub evaluation_interval: Duration,
26    /// Hot tier utilization threshold for demotion (0.0 - 1.0)
27    pub hot_tier_utilization_threshold: f64,
28    /// Warm tier utilization threshold for demotion (0.0 - 1.0)
29    pub warm_tier_utilization_threshold: f64,
30    /// Access frequency threshold for hot tier (queries/second)
31    pub hot_tier_qps_threshold: f64,
32    /// Access frequency threshold for warm tier (queries/second)
33    pub warm_tier_qps_threshold: f64,
34    /// Minimum time in tier before transition (prevents thrashing)
35    pub min_time_in_tier: Duration,
36    /// Gradual transition configuration
37    pub gradual_transition: GradualTransitionConfig,
38    /// Cost model
39    pub cost_model: TierCostModel,
40    /// Enable predictive tier management
41    pub enable_predictive_management: bool,
42    /// Enable multi-tenancy support
43    pub enable_multi_tenancy: bool,
44    /// Maximum concurrent tier transitions
45    pub max_concurrent_transitions: usize,
46    /// Enable metrics collection
47    pub enable_metrics: bool,
48    /// Metrics retention period
49    pub metrics_retention: Duration,
50    /// Enable compression in warm tier
51    pub warm_tier_compression: bool,
52    /// Enable compression in cold tier
53    pub cold_tier_compression: bool,
54    /// Warm tier compression level (1-22)
55    pub warm_tier_compression_level: i32,
56    /// Cold tier compression level (1-22)
57    pub cold_tier_compression_level: i32,
58}
59
60impl Default for TieringConfig {
61    fn default() -> Self {
62        Self {
63            hot_tier_capacity_gb: 16.0,
64            warm_tier_capacity_gb: 128.0,
65            cold_tier_capacity_gb: 1024.0,
66            policy: TieringPolicy::Adaptive,
67            storage_base_path: PathBuf::from("/var/lib/oxirs/tiered-storage"),
68            auto_tier_management: true,
69            evaluation_interval: Duration::from_secs(300), // 5 minutes
70            hot_tier_utilization_threshold: 0.8,           // 80%
71            warm_tier_utilization_threshold: 0.9,          // 90%
72            hot_tier_qps_threshold: 10.0,                  // 10 queries/sec
73            warm_tier_qps_threshold: 1.0,                  // 1 query/sec
74            min_time_in_tier: Duration::from_secs(3600),   // 1 hour
75            gradual_transition: GradualTransitionConfig::default(),
76            cost_model: TierCostModel::default(),
77            enable_predictive_management: true,
78            enable_multi_tenancy: false,
79            max_concurrent_transitions: 4,
80            enable_metrics: true,
81            metrics_retention: Duration::from_secs(7 * 24 * 3600), // 7 days
82            warm_tier_compression: true,
83            cold_tier_compression: true,
84            warm_tier_compression_level: 6,
85            cold_tier_compression_level: 19,
86        }
87    }
88}
89
90impl TieringConfig {
91    /// Validate configuration
92    pub fn validate(&self) -> anyhow::Result<()> {
93        if self.hot_tier_capacity_gb <= 0.0 {
94            anyhow::bail!("Hot tier capacity must be positive");
95        }
96        if self.warm_tier_capacity_gb <= 0.0 {
97            anyhow::bail!("Warm tier capacity must be positive");
98        }
99        if self.cold_tier_capacity_gb <= 0.0 {
100            anyhow::bail!("Cold tier capacity must be positive");
101        }
102        if self.hot_tier_utilization_threshold <= 0.0 || self.hot_tier_utilization_threshold > 1.0 {
103            anyhow::bail!("Hot tier utilization threshold must be in (0.0, 1.0]");
104        }
105        if self.warm_tier_utilization_threshold <= 0.0 || self.warm_tier_utilization_threshold > 1.0
106        {
107            anyhow::bail!("Warm tier utilization threshold must be in (0.0, 1.0]");
108        }
109        if self.hot_tier_qps_threshold < 0.0 {
110            anyhow::bail!("Hot tier QPS threshold must be non-negative");
111        }
112        if self.warm_tier_qps_threshold < 0.0 {
113            anyhow::bail!("Warm tier QPS threshold must be non-negative");
114        }
115        if self.max_concurrent_transitions == 0 {
116            anyhow::bail!("Max concurrent transitions must be at least 1");
117        }
118        if self.warm_tier_compression_level < 1 || self.warm_tier_compression_level > 22 {
119            anyhow::bail!("Warm tier compression level must be in [1, 22]");
120        }
121        if self.cold_tier_compression_level < 1 || self.cold_tier_compression_level > 22 {
122            anyhow::bail!("Cold tier compression level must be in [1, 22]");
123        }
124        Ok(())
125    }
126
127    /// Create a development configuration (smaller capacities)
128    pub fn development() -> Self {
129        Self {
130            hot_tier_capacity_gb: 1.0,
131            warm_tier_capacity_gb: 8.0,
132            cold_tier_capacity_gb: 64.0,
133            storage_base_path: PathBuf::from("/tmp/oxirs-tiered-storage"),
134            evaluation_interval: Duration::from_secs(60), // 1 minute
135            ..Default::default()
136        }
137    }
138
139    /// Create a production configuration (larger capacities, conservative settings)
140    pub fn production() -> Self {
141        Self {
142            hot_tier_capacity_gb: 64.0,
143            warm_tier_capacity_gb: 512.0,
144            cold_tier_capacity_gb: 4096.0,
145            evaluation_interval: Duration::from_secs(600), // 10 minutes
146            min_time_in_tier: Duration::from_secs(7200),   // 2 hours
147            enable_predictive_management: true,
148            ..Default::default()
149        }
150    }
151
152    /// Calculate total capacity in bytes
153    pub fn total_capacity_bytes(&self) -> u64 {
154        ((self.hot_tier_capacity_gb + self.warm_tier_capacity_gb + self.cold_tier_capacity_gb)
155            * 1024.0
156            * 1024.0
157            * 1024.0) as u64
158    }
159
160    /// Get hot tier capacity in bytes
161    pub fn hot_tier_capacity_bytes(&self) -> u64 {
162        (self.hot_tier_capacity_gb * 1024.0 * 1024.0 * 1024.0) as u64
163    }
164
165    /// Get warm tier capacity in bytes
166    pub fn warm_tier_capacity_bytes(&self) -> u64 {
167        (self.warm_tier_capacity_gb * 1024.0 * 1024.0 * 1024.0) as u64
168    }
169
170    /// Get cold tier capacity in bytes
171    pub fn cold_tier_capacity_bytes(&self) -> u64 {
172        (self.cold_tier_capacity_gb * 1024.0 * 1024.0 * 1024.0) as u64
173    }
174}
175
176#[cfg(test)]
177mod tests {
178    use super::*;
179
180    #[test]
181    fn test_default_config_is_valid() {
182        let config = TieringConfig::default();
183        assert!(config.validate().is_ok());
184    }
185
186    #[test]
187    fn test_development_config_is_valid() {
188        let config = TieringConfig::development();
189        assert!(config.validate().is_ok());
190    }
191
192    #[test]
193    fn test_production_config_is_valid() {
194        let config = TieringConfig::production();
195        assert!(config.validate().is_ok());
196    }
197
198    #[test]
199    fn test_invalid_capacity() {
200        let config = TieringConfig {
201            hot_tier_capacity_gb: -1.0,
202            ..Default::default()
203        };
204        assert!(config.validate().is_err());
205    }
206
207    #[test]
208    fn test_invalid_threshold() {
209        let config = TieringConfig {
210            hot_tier_utilization_threshold: 1.5,
211            ..Default::default()
212        };
213        assert!(config.validate().is_err());
214    }
215
216    #[test]
217    fn test_capacity_calculations() {
218        let config = TieringConfig {
219            hot_tier_capacity_gb: 1.0,
220            warm_tier_capacity_gb: 2.0,
221            cold_tier_capacity_gb: 3.0,
222            ..Default::default()
223        };
224
225        assert_eq!(config.hot_tier_capacity_bytes(), 1073741824); // 1 GB
226        assert_eq!(config.warm_tier_capacity_bytes(), 2147483648); // 2 GB
227        assert_eq!(config.cold_tier_capacity_bytes(), 3221225472); // 3 GB
228        assert_eq!(config.total_capacity_bytes(), 6442450944); // 6 GB
229    }
230}