use crate::{Context, error::CompactError};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
pub enum CompactionStage {
BudgetReduce,
Snip,
Microcompact,
ContextCollapse,
AutoCompact,
}
impl CompactionStage {
pub const ALL: [CompactionStage; 5] = [
CompactionStage::BudgetReduce,
CompactionStage::Snip,
CompactionStage::Microcompact,
CompactionStage::ContextCollapse,
CompactionStage::AutoCompact,
];
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Budget {
pub used: u32,
pub window: u32,
}
impl Budget {
pub fn ratio(&self) -> f32 {
if self.window == 0 { 0.0 } else { self.used as f32 / self.window as f32 }
}
pub fn required_stages(&self) -> Vec<CompactionStage> {
let r = self.ratio();
let mut out = Vec::new();
if r > 0.60 { out.push(CompactionStage::BudgetReduce); }
if r > 0.70 { out.push(CompactionStage::Snip); }
if r > 0.80 { out.push(CompactionStage::Microcompact); }
if r > 0.90 { out.push(CompactionStage::ContextCollapse); }
if r > 0.95 { out.push(CompactionStage::AutoCompact); }
out
}
}
#[async_trait]
pub trait Compactor: Send + Sync + 'static {
fn budget(&self, ctx: &Context) -> Budget;
async fn compact(&self, stage: CompactionStage, ctx: &mut Context) -> Result<(), CompactError>;
}