Expand description
Background jobs: one persisted row per long-running administrative operation, run on an
in-process thread with progress persisted to the database. The shared mechanism behind corpus
import/extend, service activation, runs, and dataset export. See docs/archive/JOB_MODEL.md.
Structs§
- Job
- A persisted background job.
- JobProgress
- A handle passed to a job body; each call persists progress on the job row.
Constants§
- ANALYZE_
KIND - The job
kindfor a planner-statistics refresh. - POPULATE_
REPORT_ KIND - The job
kindfor a single(corpus, service, severity)report-cache populate. - REFRESH_
REPORTS_ KIND - The job
kindfor areport_summaryrollup refresh. - REINDEX_
KIND - The job
kindfor an online index rebuild.
Functions§
- count_
recent_ with_ status - Counts jobs in terminal
statuscreated within the lasthours— a current-state observability signal for “are jobs failing / stalling lately?”. A rolling window so the gauge auto-resolves (unlike an ever-growing total-failures counter, which would alert forever after one failure). Skew-free (windowed against the DB clock). Best-effort:0on error. - db_now
- The database’s current wall clock as a tz-naive timestamp in the session timezone — i.e. the
same clock
created_at/updated_atare written in (Postgresnow()stored into atimestampcolumn). Differencing a job’supdated_atagainst this is therefore skew-free, unlike comparing against the app process’schrono::Utc::now()(which differs by the session offset when the DB is not on UTC). Used to compute a running job’s heartbeat age (W-4 stall observability). Best-effort: returnsNoneif the probe fails (a broken connection), so callers degrade to “no age” rather than reporting a bogus one. - find_
job - Finds a job by its external uuid handle.
- interrupt_
orphans - Marks any non-terminal jobs as
interrupted; call once on frontend startup so jobs that died with a previous process are not left looking live. - list_
recent - Lists recent jobs, most-recent-first, capped at
limit. Withactive_only, returns just the pending (non-terminal:queued/running) jobs — the fleet-wide observability check for any background-task capability. Best-effort: an error yields an empty list rather than propagating. - reap_
stale - Marks any non-terminal job whose progress heartbeat has been silent for longer than
config().jobs.stale_timeout_secondsasinterrupted— the runtime complement tointerrupt_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 sitrunningforever, leaking a thread and lying to every pending-check + the report-refresh debounce. A job that keepsstep-ing stays live (freshupdated_at); only a silent one is reaped. Self-correcting: if a merely-slow job is reaped and later finishes, itsfinish()overwrites the status, so a generous timeout costs at most a transientinterrupteddisplay. Skew-free (differences against the DB clock, likedb_now). Returns the count reaped; best-effort. - report_
populate_ active - Whether a populate job for exactly this
(corpus, service, severity)slice is already queued or running — the request path’s pre-check, so a burst of viewers of a still-computing report doesn’t each re-attempt the (bounded) inline aggregation while the background job is already on it. - spawn_
analyze - Spawns a background job that refreshes the query planner’s statistics with
ANALYZEover the high-churn tables. After a bulk import or a large rerun churnstasks.status, stale statistics can make the planner mis-estimate and skip the right index (e.g. the TODO leasing index,todo_index), so an operator can refresh them on demand instead of waiting for autovacuum’s next pass (DB ongoing-maintenance;docs/DB_TUNING.md).ANALYZEis online (a brief lock per table, sampling only) and runs off the request path, reporting per-table progress. Debounced: an analyze already queued/running is reused. - spawn_
job - Spawns a background job: inserts a
queuedrow, returns its uuid, and runsbodyon a thread. The body reports progress viaJobProgressand returns a terminal result or an error message. - spawn_
reindex - Spawns a background job that rebuilds the high-churn tables’ indexes online with
REINDEX (CONCURRENTLY)— no exclusive lock, so reads/writes continue (DB ongoing-maintenance;docs/DB_TUNING.md). Runs off the request path (rebuilds are minutes-to-hours at scale) and reports per-table progress. Debounced: a reindex already queued/running is reused. - spawn_
report_ populate - Spawns a background job that (re)computes one
(corpus, service, severity)report slice (rollup::populate_scope) off the request path — the heavy aggregation behind a cold report view (minutes for the full-arXivinfoslice) runs here instead of pinning a frontend connection and blocking the viewer, who is shown a “report computing” page that refreshes when the slice is ready. Debounced per scope: an already-active populate for the same slice is reused (its uuid returned) rather than spawning a duplicate. PollGET /api/jobs/<uuid>for status/health. - spawn_
report_ refresh - Spawns a background job for the manual “Force refresh” action. The global
report_summarymatview was retired in favour of a per-(corpus, service, severity) cache (report_grain_cache), so this no longer does a multi-minute rebuild: it invalidates the whole cache (a cheapDELETE, never a scan), and each report slice then repopulates lazily, per scope, on its next view. Run off the request path so the caller returns immediately.