Expand description
The GC maintenance chain’s consumer side (wave 7 — substrate.md
§GC; ADR-019 §6; POC-R’s validated cross-process run, POC-R’s
maintenance.rs): the schedule registration + the runner, the
maintenance worker’s claim loop, the leader TTL lock, and the sweep
dispatch — the chain that turns crate::reactor::MAINTENANCE_QUEUE’s
payload vocabulary (MaintenanceJob) into GC.
MaintenanceChain::register_sweep_schedule (the `@every` schedule)
→ the alkstore leader-elected scheduler (run_schedules — one
leader per fleet, the reserved `__alkstore_scheduler` lock)
→ firing lands in the maintenance queue (the `Sweep` payload)
→ worker claim (the queue's stamped visibility window is the
discipline: the worker acks inside it — a Sweep dispatch longer
than its stamped window simply lapses, and the at-least-once
redelivery is held off by these same locks: the redelivered
sweep is either a locked-out skip or an alkblobs `SweeperLock`
abort, never a concurrent double reclaim)
→ named-TTL leader lock ([`MAINTENANCE_LOCK`], cross-process GC
exclusion; a locked-out sweep is a skip + short retry, a
value not an error)
→ alkblobs Store::sweep() -> Result<SweepReport, Error>
(the report is the GC outcome carrier — stages, deletes,
aborts; Err is substrate-level failure: a data verdict + a
queue retry, the no-log-dep posture — the outcome is
observable through the [`WorkerEvent`] seam and get_job)Wave 6 landed the enqueue producer side only (the recorded interpretation, gate-confirmed); this module is the consumer side — and, the wave-6 gate’s N-b rider, the runner supervision the chain owns:
- the wake runner (
Reactor::run_wake_runner) returnsOk(())on bothrecv_timeoutErrarms (the alkstore contract’sClosedsource-death andDatabasestorage-failure arms collapsed by design), so until supervised a runner stop means wake-driven refresh stops silently —MaintenanceChain’s supervision restarts it on both stop shapes (recovery is a freshlisten,Reactor::run_wake_runner’s posture; the stale window between stop and restart is exactly what the reconcile tick exists to bound). - the reconcile tick’s driving mechanism (the wave-6 recorded
interpretation’s pinned answer): the chain itself ticks it —
MaintenanceOpts::reconcile_tick, oneReactor::reconcilepass per tick alongside the worker loop. (Of the three candidates — a schedule firing, a worker-loop tick, a dedicated job — the chain tick is the shape the supervision already owns: schedule firings land GC jobs into the queue, and a reconcile job variant would be a second vocabulary member for what the runner owns anyway.) - the scheduler runner supervision:
run_schedulesrespawns onErr(LeadershipLost)(the alkstore recipe) and propagates any other stop — a substrate-level failure of the scheduler leg is the chain’s failure (the closed-store posture: respawning against a dead store is misdirected).
§The pack-housekeeping consumer (pinned in-task)
The PackHousekeeping job’s consumer action is the through-store
pack cache’s release path (PackCache::release_all) — the
released packs’ pins drop, and the next sweep reclaims their pack
blobs (substrate.md §object storage). The whole cache releases:
the request-digest cache is process-local, per-repo scoping is a
non-goal, and the enqueue leg’s repo id is observation data only. An
assembly without a through-store PackGen
carries no cache (MaintenanceChain::new’s packs: None) — such
a job acks with nothing to release, the composition-honest shape.
§The sweep verdicts (data, never errors)
- a completed report (
SweepReport.abortedincluded — an aborted sweep is still a ran sweep, its result carried) — acked; - a locked-out sweep (
MAINTENANCE_LOCKheld elsewhere — cross-process GC exclusion is the point) — a skip + short retry, a value: the job goes back to pending withLOCKED_OUT_RETRY_SECS; - a substrate-level sweep failure (alkblobs
Err) — a data verdict + a queue retry (the at-least-once curve runs it again; max attempts dead-letters it, observable via get_job).
A poison payload (a foreign producer on the queue, codec drift)
dead-letters immediately (fail) — the stream consumer’s poison
posture, queue-shaped: never a wedge, never a retry loop.
Structs§
- Maintenance
Chain - The maintenance chain’s consumer side — the schedule registration + the runner, the worker’s claim loop, the leader TTL lock, the sweep dispatch, and the supervised halves the wave-6 gate booked the chain to own (the wake runner’s restart on both stop shapes; the reconcile tick’s driving).
- Maintenance
Opts - The chain’s tuning datums (assembly-level knobs, not structure — the schedule spec is the sweep cadence; the tick is the postgres staleness bound; the rest is the loop granularity).
Enums§
- Sweep
Verdict - A sweep job’s outcome, as data (substrate.md §GC — the chain never turns a sweep outcome into an error).
- Worker
Event - What the maintenance worker did — the observation seam (the
logged-as-data posture: the outcome carriers surface here, no
tracing dependency exists anywhere). A consumer of
MaintenanceChain::runsees every executed or skipped job.
Constants§
- LOCKED_
OUT_ RETRY_ SECS - Seconds a locked-out sweep goes back to pending for (the short retry — a value, not an error; ADR-019 §6; the schedule’s own cadence is the backstop after it).
- SWEEP_
SCHEDULE - The sweep schedule’s name — registered (upsert by name) firing
into
MAINTENANCE_QUEUEwith theMaintenanceJob::Sweeppayload (the POC-R-validated schedule; the chain’s runner supervision owns therun_schedulesside).