Skip to main content

run_checkpoint_task

Function run_checkpoint_task 

Source
pub async fn run_checkpoint_task(
    pool: Arc<ConnectionPool>,
    config: CheckpointConfig,
    lifecycle_owner: Option<CheckpointLifecycleOwner>,
    shutdown_rx: Receiver<()>,
    is_main: bool,
)
Expand description

Run the WAL checkpoint background task.

Long-running async task — spawn with tokio::spawn. Loops until shutdown_rx observes a change (or its sender is dropped). Callers MUST hold the paired tokio::sync::watch::Sender for the daemon’s run scope and send on it to shut down — do NOT rely on pool’s Arc refcount reaching zero; a sibling owner (e.g. event_store) holding its own clone makes that check unreachable (issue #774).

Issues PRAGMA wal_checkpoint(PASSIVE) every tick on the task’s dedicated CheckpointConnection — never the pool’s writer mutex, so a concurrent pool.writer() checkout can never queue behind a checkpoint tick. That guarantee is admission-only: an armed TRUNCATE still takes SQLite’s writer lock and can block new write transactions, on any connection, for up to truncate_busy_timeout (see CheckpointConnection’s contract). The checkpoint call itself runs on spawn_blocking, so that wait never holds one of the runtime’s worker threads. A tick is Skipped when that connection is unavailable or SQLite returns a busy PASSIVE row without a usable pressure observation. A WARNING fires once per below→above threshold crossing, not every tick.

lifecycle_owner (ADR-094): exactly one task in a multi-backend fan-out should receive Some. That task appends a best-effort CheckpointOutcomeRecorded event on the elevation transition and one recovery summary when pressure falls back below warn_pages. Sustained elevated ticks aggregate in memory and in db_diagnostics; they never write one primary-store row per checkpoint attempt. None explicitly marks a non-owner. See crates/khive-db/docs/api/checkpoint.md for the full shutdown-mechanism and event-emission design history.

is_main (ADR-091 Amendment 3): whether pool is the deployment’s main backend. A daemon owning several file-backed backends spawns one task per backend, each with its own pool and shutdown-channel clone (the sender broadcasts to every receiver clone alike). Lifecycle ownership is selected independently through lifecycle_owner; is_main only controls registry filtering. See the tx_filter construction below.