Skip to main content

reap_stale

Function reap_stale 

Source
pub fn reap_stale(connection: &mut PgConnection) -> usize
Expand description

Marks any non-terminal job whose progress heartbeat has been silent for longer than config().jobs.stale_timeout_seconds as interrupted — the runtime complement to interrupt_orphans (which only runs at startup). It closes the W-4 zombie: a job whose body hangs while a long-lived frontend keeps running would otherwise sit running forever, leaking a thread and lying to every pending-check + the report-refresh debounce. A job that keeps step-ing stays live (fresh updated_at); only a silent one is reaped. Self-correcting: if a merely-slow job is reaped and later finishes, its finish() overwrites the status, so a generous timeout costs at most a transient interrupted display. Skew-free (differences against the DB clock, like db_now). Returns the count reaped; best-effort.

Caveat — Rust cannot force-kill a thread: reaping marks the DB row terminal (so accounting, pending-checks, and the refresh debounce are correct) but the hung OS thread itself runs until its body unblocks. The leak is bounded — its pooled connection is returned between steps and the r2d2 pool caps total connections — but the thread/stack is only reclaimed when the body returns; truly aborting a hung blocking job would need subprocess isolation (a SIGKILL-able child), a deliberate architecture trade. See the W-4 ledger entry.