harness_core/
compactor.rs1use crate::{Context, error::CompactError};
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[serde(rename_all = "kebab-case")]
8#[non_exhaustive]
9pub enum CompactionStage {
10 BudgetReduce,
12 Snip,
14 Microcompact,
16 ContextCollapse,
18 AutoCompact,
20}
21
22impl CompactionStage {
23 pub const ALL: [CompactionStage; 5] = [
25 CompactionStage::BudgetReduce,
26 CompactionStage::Snip,
27 CompactionStage::Microcompact,
28 CompactionStage::ContextCollapse,
29 CompactionStage::AutoCompact,
30 ];
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub struct Budget {
35 pub used: u32,
36 pub window: u32,
37}
38
39impl Budget {
40 pub fn ratio(&self) -> f32 {
41 if self.window == 0 {
42 0.0
43 } else {
44 self.used as f32 / self.window as f32
45 }
46 }
47
48 pub fn required_stages(&self) -> Vec<CompactionStage> {
50 let r = self.ratio();
51 let mut out = Vec::new();
52 if r > 0.60 {
53 out.push(CompactionStage::BudgetReduce);
54 }
55 if r > 0.70 {
56 out.push(CompactionStage::Snip);
57 }
58 if r > 0.80 {
59 out.push(CompactionStage::Microcompact);
60 }
61 if r > 0.90 {
62 out.push(CompactionStage::ContextCollapse);
63 }
64 if r > 0.95 {
65 out.push(CompactionStage::AutoCompact);
66 }
67 out
68 }
69}
70
71#[async_trait]
72pub trait Compactor: Send + Sync + 'static {
73 fn budget(&self, ctx: &Context) -> Budget;
74 async fn compact(&self, stage: CompactionStage, ctx: &mut Context) -> Result<(), CompactError>;
75}