use crate::cache::CacheConfig;
use do_memory_storage_redb::{AdaptiveCache, AdaptiveCacheConfig};
use std::sync::atomic::AtomicU64;
use std::sync::Arc;
use std::time::Duration;
use tracing::warn;
use uuid::Uuid;
#[derive(Debug, Clone)]
pub struct AdaptiveTtlConfig {
pub base_config: AdaptiveCacheConfig,
pub enable_memory_pressure: bool,
pub memory_threshold: f64,
pub heap_size_threshold: usize,
pub enable_hybrid_eviction: bool,
pub lru_weight: f64,
pub time_decay_factor: f64,
pub decay_interval_secs: u64,
pub enable_time_decay: bool,
pub min_items_to_keep: usize,
pub pressure_multiplier: f64,
}
impl Default for AdaptiveTtlConfig {
fn default() -> Self {
Self {
base_config: AdaptiveCacheConfig::default(),
enable_memory_pressure: true,
memory_threshold: 0.8, heap_size_threshold: 100 * 1024 * 1024, enable_hybrid_eviction: true,
lru_weight: 0.5, time_decay_factor: 0.1, decay_interval_secs: 60,
enable_time_decay: true,
min_items_to_keep: 100,
pressure_multiplier: 2.0,
}
}
}
impl From<AdaptiveTtlConfig> for CacheConfig {
fn from(config: AdaptiveTtlConfig) -> Self {
CacheConfig {
enable_episode_cache: true,
enable_pattern_cache: true,
enable_query_cache: true,
max_episodes: config.base_config.max_size,
max_patterns: config.base_config.max_size / 2,
max_query_results: config.base_config.max_size / 10,
episode_ttl: config.base_config.default_ttl,
pattern_ttl: config.base_config.default_ttl,
query_ttl: Duration::from_secs(300),
min_ttl: config.base_config.min_ttl,
max_ttl: config.base_config.max_ttl,
hot_threshold: config.base_config.hot_threshold,
cold_threshold: config.base_config.cold_threshold,
adaptation_rate: config.base_config.adaptation_rate,
enable_background_cleanup: config.base_config.enable_background_cleanup,
cleanup_interval_secs: config.base_config.cleanup_interval_secs,
}
}
}
#[derive(Debug)]
struct MemoryPressureState {
last_heap_size: usize,
pressure_level: PressureLevel,
pressure_evictions: u64,
last_check: std::time::Instant,
}
impl Default for MemoryPressureState {
fn default() -> Self {
Self {
last_heap_size: 0,
pressure_level: PressureLevel::Normal,
pressure_evictions: 0,
last_check: std::time::Instant::now(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum PressureLevel {
Normal,
Low,
High,
Critical,
}
impl Default for PressureLevel {
fn default() -> Self {
PressureLevel::Normal
}
}
#[derive(Debug)]
struct HybridEvictionState {
lru_scores: Vec<(Uuid, u64)>, lfu_scores: Vec<(Uuid, usize)>, hybrid_scores: Vec<(Uuid, f64)>, last_recalc: std::time::Instant,
}
impl Default for HybridEvictionState {
fn default() -> Self {
Self {
lru_scores: Vec::new(),
lfu_scores: Vec::new(),
hybrid_scores: Vec::new(),
last_recalc: std::time::Instant::now(),
}
}
}
#[derive(Debug, Default)]
pub struct AdaptiveTtlStats {
pub hits: AtomicU64,
pub misses: AtomicU64,
pub evictions: AtomicU64,
pub pressure_evictions: AtomicU64,
pub size_evictions: AtomicU64,
pub ttl_evictions: AtomicU64,
pub ttl_adaptations: AtomicU64,
pub pressure_changes: AtomicU64,
pub decay_time_us: AtomicU64,
pub current_pressure: AtomicU64, pub hit_rate: AtomicU64, }
impl AdaptiveTtlStats {
pub fn record_hit(&self) {
self.hits.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
self.update_hit_rate();
}
pub fn record_miss(&self) {
self.misses
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
self.update_hit_rate();
}
fn update_hit_rate(&self) {
let hits = self.hits.load(std::sync::atomic::Ordering::Relaxed);
let misses = self.misses.load(std::sync::atomic::Ordering::Relaxed);
let total = hits + misses;
let rate = if total > 0 {
(hits as f64 / total as f64) * 100.0
} else {
0.0
};
self.hit_rate
.store(rate as u64, std::sync::atomic::Ordering::Relaxed);
}
pub fn hit_rate_percent(&self) -> f64 {
self.hit_rate.load(std::sync::atomic::Ordering::Relaxed) as f64
}
pub fn pressure_level(&self) -> PressureLevel {
match self
.current_pressure
.load(std::sync::atomic::Ordering::Relaxed)
{
0 => PressureLevel::Normal,
1 => PressureLevel::Low,
2 => PressureLevel::High,
3 => PressureLevel::Critical,
_ => PressureLevel::Normal,
}
}
}
#[derive(Debug, Clone)]
pub struct CacheEffectivenessReport {
pub hit_rate_percent: f64,
pub pressure_level: PressureLevel,
pub cache_size: usize,
pub item_count: usize,
pub total_evictions: u64,
pub pressure_evictions: u64,
pub ttl_adaptations: u64,
pub effectiveness_score: f64,
pub recommendations: Vec<String>,
}
pub(crate) fn estimate_heap_size() -> usize {
if let Ok(status) = std::fs::read_to_string("/proc/self/status") {
for line in status.lines() {
if line.starts_with("VmRSS:") {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
if let Ok(kb) = parts[1].parse::<usize>() {
return kb * 1024; }
}
}
}
}
0
}