Initial Meterbox commit with boot disk usage metric.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
JamesandCursor committed 2026-09-19 02:45:52 +00:00
commit 4e44204d9b
55 files changed
+12104

No files matched your search

+64
View File
@@ -0,0 +1,64 @@
use std::time::Duration;
use crate::AppState;
/// Background job: age retention + hard SQLite size cap (default 10 GiB).
pub fn spawn(state: AppState) {
tokio::spawn(async move {
// Run once shortly after boot, then on the configured cadence.
tokio::time::sleep(Duration::from_secs(15)).await;
run_once(&state);
let secs = state.config.cleanup_interval_secs.max(60);
let mut ticker = tokio::time::interval(Duration::from_secs(secs));
ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
// Skip the immediate first tick (already ran above).
ticker.tick().await;
loop {
ticker.tick().await;
run_once(&state);
}
});
}
fn run_once(state: &AppState) {
let max = state.config.max_db_bytes;
// Aim for 90% of the cap so we don't thrash at the ceiling.
let target = (max as f64 * 0.90) as u64;
match state
.db
.run_cleanup(state.config.retention_days, max, target)
{
Ok(report) => {
tracing::info!(
deleted_by_age = report.deleted_by_age,
deleted_by_size = report.deleted_by_size,
vacuumed = report.vacuumed,
bytes_before = report.bytes_before,
bytes_after = report.bytes_after,
rows = report.rows_after,
max_bytes = max,
"sqlite cleanup finished"
);
}
Err(e) => tracing::warn!(error = %e, "sqlite cleanup failed"),
}
match state.db.get_settings() {
Ok(settings) if settings.cleanup_logs_older_than_3_months => {
match state
.db
.prune_health_results_older_than(crate::settings::HEALTH_LOG_RETENTION_DAYS)
{
Ok(n) if n > 0 => {
tracing::info!(deleted = n, "pruned health logs older than 3 months")
}
Ok(_) => {}
Err(e) => tracing::warn!(error = %e, "health log prune failed"),
}
}
Ok(_) => {}
Err(e) => tracing::warn!(error = %e, "load settings for cleanup failed"),
}
}