feat: add WAL checkpoint task and improve Landlock fallback logging

Add periodic PRAGMA wal_checkpoint(TRUNCATE) every 5 minutes for both
sessions.db and btmsg.db to prevent unbounded WAL growth under sustained
multi-agent load. Improve Landlock fallback log message with kernel
version requirement. Add WAL checkpoint tests.
This commit is contained in:
Hibryda 2026-03-12 05:21:39 +01:00 committed by DexterFromLab
parent de8d1488e2
commit 9af3cdc637
3 changed files with 83 additions and 2 deletions

View file

@ -25,7 +25,7 @@ use session::SessionDb;
use sidecar::{SidecarConfig, SidecarManager};
use fs_watcher::ProjectFsWatcher;
use watcher::FileWatcherManager;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tauri::Manager;
@ -104,6 +104,40 @@ fn install_cli_tools(resource_dir: &Path, dev_root: &Path) {
}
}
/// Run `PRAGMA wal_checkpoint(TRUNCATE)` on a SQLite database to reclaim WAL file space.
/// Returns Ok(()) on success or Err with a diagnostic message.
pub(crate) fn checkpoint_wal(path: &Path) -> Result<(), String> {
use rusqlite::{Connection, OpenFlags};
if !path.exists() {
return Ok(()); // DB doesn't exist yet — nothing to checkpoint
}
let conn = Connection::open_with_flags(path, OpenFlags::SQLITE_OPEN_READ_WRITE)
.map_err(|e| format!("WAL checkpoint: failed to open {}: {e}", path.display()))?;
conn.query_row("PRAGMA busy_timeout = 5000", [], |_| Ok(()))
.map_err(|e| format!("WAL checkpoint: failed to set busy_timeout: {e}"))?;
conn.query_row("PRAGMA wal_checkpoint(TRUNCATE)", [], |_| Ok(()))
.map_err(|e| format!("WAL checkpoint failed on {}: {e}", path.display()))?;
Ok(())
}
/// Spawn a background task that checkpoints WAL on both databases every 5 minutes.
fn spawn_wal_checkpoint_task(sessions_db_path: PathBuf, btmsg_db_path: PathBuf) {
tokio::spawn(async move {
let interval = std::time::Duration::from_secs(300);
loop {
tokio::time::sleep(interval).await;
for (label, path) in [("sessions.db", &sessions_db_path), ("btmsg.db", &btmsg_db_path)] {
match checkpoint_wal(path) {
Ok(()) => tracing::info!("WAL checkpoint completed for {label}"),
Err(e) => tracing::warn!("WAL checkpoint error for {label}: {e}"),
}
}
}
});
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
// Force dark GTK theme for native dialogs (file chooser, etc.)
@ -347,6 +381,11 @@ pub fn run() {
Err(e) => log::warn!("Sidecar startup failed (agent features unavailable): {e}"),
}
// Start periodic WAL checkpoint task (every 5 minutes)
let sessions_db_path = config.data_dir.join("sessions.db");
let btmsg_db_path = config.btmsg_db_path();
spawn_wal_checkpoint_task(sessions_db_path, btmsg_db_path);
app.manage(AppState {
pty_manager,
sidecar_manager,