use std::path::PathBuf;
use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum PersistenceMode {
Full,
Incremental,
#[default]
Hybrid,
Disabled,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum PersistenceStrategy {
Immediate,
#[default]
Interval,
OnShutdown,
Threshold,
}
#[derive(Debug, Clone)]
pub struct PersistenceConfig {
pub enabled: bool,
pub persistence_path: PathBuf,
pub mode: PersistenceMode,
pub strategy: PersistenceStrategy,
pub save_interval: Duration,
pub min_entries_threshold: usize,
pub max_entries: usize,
pub compression_enabled: bool,
pub compression_level: u32,
pub encryption_enabled: bool,
pub max_snapshot_age_secs: u64,
pub backup_count: usize,
}
impl Default for PersistenceConfig {
fn default() -> Self {
Self {
enabled: true,
persistence_path: PathBuf::from("./cache.redb.snapshot"),
mode: PersistenceMode::default(),
strategy: PersistenceStrategy::default(),
save_interval: Duration::from_secs(300), min_entries_threshold: 100,
max_entries: 100_000,
compression_enabled: true,
compression_level: 6,
encryption_enabled: false,
max_snapshot_age_secs: 3600, backup_count: 3,
}
}
}
impl PersistenceConfig {
pub fn with_path(path: impl Into<PathBuf>) -> Self {
Self {
persistence_path: path.into(),
..Default::default()
}
}
pub fn disabled() -> Self {
Self {
enabled: false,
..Default::default()
}
}
pub fn with_immediate_strategy(mut self) -> Self {
self.strategy = PersistenceStrategy::Immediate;
self
}
pub fn with_interval(mut self, interval: Duration) -> Self {
self.strategy = PersistenceStrategy::Interval;
self.save_interval = interval;
self
}
pub fn with_shutdown_strategy(mut self) -> Self {
self.strategy = PersistenceStrategy::OnShutdown;
self
}
pub fn with_min_entries(mut self, threshold: usize) -> Self {
self.min_entries_threshold = threshold;
self
}
pub fn with_max_entries(mut self, max: usize) -> Self {
self.max_entries = max;
self
}
pub fn with_compression(mut self, enabled: bool) -> Self {
self.compression_enabled = enabled;
self
}
pub fn with_compression_level(mut self, level: u32) -> Self {
self.compression_level = level.clamp(0, 9);
self
}
pub fn with_backup_count(mut self, count: usize) -> Self {
self.backup_count = count;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = PersistenceConfig::default();
assert!(config.enabled);
assert_eq!(config.mode, PersistenceMode::Hybrid);
assert_eq!(config.strategy, PersistenceStrategy::Interval);
assert_eq!(config.save_interval, Duration::from_secs(300));
assert_eq!(config.min_entries_threshold, 100);
assert!(config.compression_enabled);
assert_eq!(config.compression_level, 6);
assert!(!config.encryption_enabled);
}
#[test]
fn test_disabled_config() {
let config = PersistenceConfig::disabled();
assert!(!config.enabled);
}
#[test]
fn test_builder_methods() {
let config = PersistenceConfig::default()
.with_immediate_strategy()
.with_min_entries(50)
.with_max_entries(1000)
.with_compression(false)
.with_compression_level(9)
.with_backup_count(5);
assert_eq!(config.strategy, PersistenceStrategy::Immediate);
assert_eq!(config.min_entries_threshold, 50);
assert_eq!(config.max_entries, 1000);
assert!(!config.compression_enabled);
assert_eq!(config.compression_level, 9);
assert_eq!(config.backup_count, 5);
}
#[test]
fn test_interval_config() {
let config = PersistenceConfig::default().with_interval(Duration::from_secs(60));
assert_eq!(config.strategy, PersistenceStrategy::Interval);
assert_eq!(config.save_interval, Duration::from_secs(60));
}
#[test]
fn test_shutdown_strategy() {
let config = PersistenceConfig::default().with_shutdown_strategy();
assert_eq!(config.strategy, PersistenceStrategy::OnShutdown);
}
#[test]
fn test_compression_level_clamping() {
let config = PersistenceConfig::default().with_compression_level(15);
assert_eq!(config.compression_level, 9);
let config = PersistenceConfig::default().with_compression_level(5);
assert_eq!(config.compression_level, 5);
}
}