feat: add usage daily rollups, incremental auto-vacuum, and sync-aware backup

- Add usage_daily_rollups table (schema v6) to aggregate proxy request
  logs into daily summaries, reducing query overhead for statistics
- Add rollup_and_prune DAO that aggregates old detail logs (>N days)
  into rollup rows and deletes the originals
- Update all usage stats queries to UNION detail logs with rollup data
- Introduce incremental auto-vacuum for SQLite, with startup and
  periodic cleanup of old stream_check_logs and request log rollups
- Split backup export/import into full vs sync variants: WebDAV sync
  now skips local-only table data (proxy_request_logs,
  stream_check_logs, provider_health, proxy_live_backup,
  usage_daily_rollups) while preserving them on import
- Add enable_logging guard to skip request log writes when disabled
- Apply cargo fmt formatting fixes across multiple modules
This commit is contained in:
Jason
2026-03-08 17:18:21 +08:00
parent 3f711d6504
commit bf40b0138c
16 changed files with 910 additions and 97 deletions
+30
View File
@@ -9,6 +9,7 @@ use indexmap::IndexMap;
use rusqlite::{params, Connection};
use serde_json::json;
use std::collections::HashMap;
use tempfile::NamedTempFile;
const LEGACY_SCHEMA_SQL: &str = r#"
CREATE TABLE providers (
@@ -633,3 +634,32 @@ fn schema_model_pricing_is_seeded_on_init() {
gemini_count
);
}
#[test]
fn ensure_incremental_auto_vacuum_rebuilds_existing_file_db() {
let temp = NamedTempFile::new().expect("create temp db file");
let path = temp.path().to_path_buf();
let conn = Connection::open(&path).expect("open temp db");
conn.execute("PRAGMA auto_vacuum = NONE;", [])
.expect("set none auto_vacuum");
Database::create_tables_on_conn(&conn).expect("create tables");
assert_eq!(
Database::get_auto_vacuum_mode(&conn).expect("auto_vacuum before rebuild"),
0,
"existing file db should start with NONE auto_vacuum"
);
let rebuilt =
Database::ensure_incremental_auto_vacuum_on_conn(&conn).expect("enable incremental mode");
assert!(rebuilt, "existing db should require rebuild via VACUUM");
drop(conn);
let reopened = Connection::open(&path).expect("reopen temp db");
assert_eq!(
Database::get_auto_vacuum_mode(&reopened).expect("auto_vacuum after rebuild"),
2,
"file db should persist INCREMENTAL auto_vacuum after VACUUM rebuild"
);
}