use dig_store::CapsuleIdentity;
#[derive(Debug, Clone, Copy)]
pub struct EvictionEntry {
pub id: CapsuleIdentity,
pub size: u64,
pub last_access: u64,
pub pinned: bool,
}
pub struct EvictionContext<'a> {
pub entries: &'a [EvictionEntry],
pub current_bytes: u64,
pub capacity: u64,
pub incoming_size: u64,
}
impl EvictionContext<'_> {
pub fn bytes_to_free(&self) -> u64 {
(self.current_bytes.saturating_add(self.incoming_size)).saturating_sub(self.capacity)
}
}
pub trait EvictionPolicy: Send + Sync {
fn select_evictions(&self, ctx: &EvictionContext<'_>) -> Vec<CapsuleIdentity>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct LruPolicy;
impl EvictionPolicy for LruPolicy {
fn select_evictions(&self, ctx: &EvictionContext<'_>) -> Vec<CapsuleIdentity> {
let need = ctx.bytes_to_free();
if need == 0 {
return Vec::new();
}
let mut coldest_first: Vec<&EvictionEntry> =
ctx.entries.iter().filter(|entry| !entry.pinned).collect();
coldest_first.sort_by_key(|entry| entry.last_access);
let mut freed = 0u64;
let mut victims = Vec::new();
for entry in coldest_first {
if freed >= need {
break;
}
freed = freed.saturating_add(entry.size);
victims.push(entry.id);
}
victims
}
}