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.