events.sqlite vacuum moves host-side

retention is a host concern — agents have no business doing their
own cleanup, and a misbehaving harness could skip it. drop
spawn_events_vacuum from both hive-ag3nt and hive-m1nd, drop the
matching Bus::vacuum + EventStore::vacuum methods. new
hive_c0re::events_vacuum module sweeps every existing
agents/<name>/state/hyperhive-events.sqlite on the same hourly
cadence as the broker vacuum. same two-stage delete (older than 7
days, trim to 2000 newest). called from main alongside broker
vacuum.

also: server-side state badge entered into todo.md (today's badge
is derived client-side from sse, fine for idle/thinking but a
state machine that grows compacting/napping wants authoritative
status from the harness).
This commit is contained in:
müde 2026-05-15 20:10:34 +02:00
parent 897e7c07ae
commit 89ccc5e6c5
6 changed files with 89 additions and 63 deletions

View file

@ -115,28 +115,6 @@ impl EventStore {
Ok(out)
}
/// Drop rows older than `older_than_secs` AND any rows beyond
/// `keep_rows` newest. Two-stage so a quiet agent keeps a useful
/// tail and a chatty one is bounded.
fn vacuum(&self, older_than_secs: i64, keep_rows: usize) -> rusqlite::Result<u64> {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.ok()
.and_then(|d| i64::try_from(d.as_secs()).ok())
.unwrap_or(0);
let cutoff = now - older_than_secs;
let conn = self.conn.lock().unwrap();
let by_age = conn.execute("DELETE FROM events WHERE ts < ?1", params![cutoff])?;
let keep_i = i64::try_from(keep_rows).unwrap_or(i64::MAX);
let by_count = conn.execute(
"DELETE FROM events
WHERE id NOT IN (
SELECT id FROM events ORDER BY id DESC LIMIT ?1
)",
params![keep_i],
)?;
Ok(u64::try_from(by_age + by_count).unwrap_or(0))
}
}
#[derive(Clone)]
@ -195,12 +173,6 @@ impl Bus {
store.recent(HISTORY_CAPACITY).unwrap_or_default()
}
/// Drop events older than `older_than_secs` and keep only the
/// newest `keep_rows`. Called periodically by the harness.
pub fn vacuum(&self, older_than_secs: i64, keep_rows: usize) -> u64 {
let Some(store) = &self.store else { return 0 };
store.vacuum(older_than_secs, keep_rows).unwrap_or(0)
}
}
impl Default for Bus {