65 lines
2.2 KiB
Rust
65 lines
2.2 KiB
Rust
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"),
|
|
}
|
|
}
|