use std::time::Duration;
#[derive(Debug, Clone, PartialEq)]
pub struct DataStoreConfig {
pub max_entries: usize,
pub max_entry_size: usize,
pub default_ttl: Option<Duration>,
pub max_ttl: Option<Duration>,
pub enable_metrics: bool,
pub memory_alert_threshold: f64,
}
impl Default for DataStoreConfig {
fn default() -> Self {
Self {
max_entries: 10_000,
max_entry_size: 1_048_576, default_ttl: None,
max_ttl: Some(Duration::from_secs(3600)), enable_metrics: true,
memory_alert_threshold: 80.0, }
}
}
#[derive(Debug, thiserror::Error)]
pub enum ConfigValidationError {
#[error("default_ttl ({default:?}) exceeds max_ttl ({max:?})")]
DefaultTtlExceedsMax {
default: Duration,
max: Duration,
},
#[error("memory_alert_threshold ({value}) must be between 0.0 and 100.0")]
MemoryAlertThreshold {
value: f64,
},
}
impl DataStoreConfig {
pub fn validate(&self) -> Result<(), ConfigValidationError> {
if let (Some(default), Some(max)) = (self.default_ttl, self.max_ttl)
&& default > max
{
return Err(ConfigValidationError::DefaultTtlExceedsMax { default, max });
}
if !(0.0..=100.0).contains(&self.memory_alert_threshold) {
return Err(ConfigValidationError::MemoryAlertThreshold {
value: self.memory_alert_threshold,
});
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = DataStoreConfig::default();
assert_eq!(config.max_entries, 10_000);
assert_eq!(config.max_entry_size, 1_048_576);
assert_eq!(config.default_ttl, None);
assert_eq!(config.max_ttl, Some(Duration::from_secs(3600)));
assert!(config.enable_metrics);
assert!(
(config.memory_alert_threshold - 80.0).abs() < f64::EPSILON,
"memory_alert_threshold should be 80.0"
);
}
#[test]
fn test_valid_config() {
let config = DataStoreConfig {
default_ttl: Some(Duration::from_secs(300)),
max_ttl: Some(Duration::from_secs(3600)),
..Default::default()
};
assert!(
matches!(config.validate(), Ok(())),
"expected DataStoreConfig::validate() to succeed when default_ttl is less than max_ttl"
);
}
#[test]
fn test_default_ttl_exceeds_max() {
let config = DataStoreConfig {
default_ttl: Some(Duration::from_secs(7200)), max_ttl: Some(Duration::from_secs(3600)), ..Default::default()
};
assert!(
matches!(
config.validate(),
Err(ConfigValidationError::DefaultTtlExceedsMax { .. })
),
"expected DataStoreConfig::validate() to return ConfigValidationError when default_ttl exceeds max_ttl"
);
}
#[test]
fn test_none_ttls_are_valid() {
let config = DataStoreConfig {
default_ttl: None,
max_ttl: None,
..Default::default()
};
assert!(
matches!(config.validate(), Ok(())),
"expected DataStoreConfig::validate() to succeed when both TTL values are None"
);
}
#[test]
fn test_only_default_ttl_is_valid() {
let config = DataStoreConfig {
default_ttl: Some(Duration::from_secs(300)),
max_ttl: None,
..Default::default()
};
assert!(
matches!(config.validate(), Ok(())),
"expected DataStoreConfig::validate() to succeed when only default_ttl is set"
);
}
#[test]
fn test_only_max_ttl_is_valid() {
let config = DataStoreConfig {
default_ttl: None,
max_ttl: Some(Duration::from_secs(3600)),
..Default::default()
};
assert!(
matches!(config.validate(), Ok(())),
"expected DataStoreConfig::validate() to succeed when only max_ttl is set"
);
}
#[test]
fn test_memory_alert_threshold_valid() {
let config = DataStoreConfig {
memory_alert_threshold: 0.0,
..Default::default()
};
assert!(
matches!(config.validate(), Ok(())),
"expected DataStoreConfig::validate() to succeed when memory_alert_threshold is 0.0"
);
let config = DataStoreConfig {
memory_alert_threshold: 100.0,
..Default::default()
};
assert!(
matches!(config.validate(), Ok(())),
"expected DataStoreConfig::validate() to succeed when memory_alert_threshold is 100.0"
);
let config = DataStoreConfig {
memory_alert_threshold: 50.0,
..Default::default()
};
assert!(
matches!(config.validate(), Ok(())),
"expected DataStoreConfig::validate() to succeed when memory_alert_threshold is 50.0"
);
}
#[test]
fn test_memory_alert_threshold_invalid() {
let config = DataStoreConfig {
memory_alert_threshold: -1.0,
..Default::default()
};
assert!(
matches!(
config.validate(),
Err(ConfigValidationError::MemoryAlertThreshold { .. })
),
"expected DataStoreConfig::validate() to return MemoryAlertThreshold when memory_alert_threshold is < 0.0"
);
let config = DataStoreConfig {
memory_alert_threshold: 101.0,
..Default::default()
};
assert!(
matches!(
config.validate(),
Err(ConfigValidationError::MemoryAlertThreshold { .. })
),
"expected DataStoreConfig::validate() to return MemoryAlertThreshold when memory_alert_threshold is > 100.0"
);
}
}