Expand description
The disk janitor: finished runs get their worktrees folded, worktrees whose run record is already gone get reclaimed too, and the shared build cache is pruned to its cap.
A run’s state being written by an older schema is not the same thing as it
being unreadable, and this module used to conflate the two: fold_due
treated any run.json its version check rejected exactly like one that
failed to parse at all, so a single schema bump silently stopped every
automatic fold in the fleet the moment it shipped, and did so with no
counter and no log line to say so. A record magi genuinely cannot parse —
missing fields, broken JSON, a schema newer than this build has ever heard
of — is still left alone here, still counted in
Housekeeping::unreadable, and still only ever removed by an explicit
operator action (magi fold, or the equivalent phone route). One written
by a schema this build merely disagrees with the meaning of is not that:
as long as it still parses, folding proceeds regardless of the number in
its schema field.
Everything policy-shaped — which statuses are foldable, how long a finished run is left alone, whether the cache is over its limit — is a pure function injected with numbers, so nothing here has to ask the operating system to be testable. The only I/O is the removal itself.
Structs§
- Housekeeping
- What one janitor pass did, for the caller’s log line.
Functions§
- abandon_
settled_ questions - Abandon every open question whose run has already settled into a status
nothing comes back from, worded with what the run became - the same
cleanup
graph::Runner::settle_questionsruns the momentstatuslands there, for questions that missed it. - cache_
report - The cache’s path, size and cap, for
magi cache showand the health view.Nonewhen the config declares noCARGO_TARGET_DIRto aggregate. - cache_
size - Size in bytes of the shared build cache.
- clear_
abandoned_ active magi fold’s recovery path for a run whose worktrees are already gone — socrate::graph::fold_runremoved nothing — but whoserun.jsonstill lists active seats nobody is left to answer for: no live daemon claims the run, and every one of those seats has overrun its own timeout (seeRunState::active_all_overrun). Clearing them and failing the run is what lets it be deleted afterward —RunState::ensure_can_deleteonly ever checks whether a live daemon is working on the run and whether its candidates are folded, notstatus, but a run stuckimplementingforever with an empty worktree still reads as unresolved everywhere else (magi show, the deck, the phone) until this runs.- due
- Is
updatedold enough, measured againstnow, that the run may fold? - fold_
due - Fold every run that is finished, older than the grace period, and not being
worked on; return
(folded, unreadable). - fold_
orphaned_ worktrees - Reclaim worktrees under
worktrees_rootthat no run record inrunsclaims anymore, and return how many were removed. - fold_
unreadable - Remove a run that cannot be read: its state directory under
runsand its worktree directory underworktrees_root. - housekeep
- Run the janitor: fold due runs, reclaim orphaned worktrees, prune stale worktree registrations, then prune the cache if it is over its cap.
- prune_
cache - Delete files from the shared build cache until it fits its cap — but only
while nobody live is registered as using it.
crate::cache::maintenance_prunetakes out the same lease a build would, so a prune can never race a compile in flight (this run’s own, another run’s, or a human’smagi review) into deleting a file that build still needs.Ok(None)when the cache is in use right now; the next pass catches it once the borrower releases it, the same way a cap of0or a missingCARGO_TARGET_DIRalready meant “nothing to do this time” here. - prune_
cache_ if_ over_ limit prune_cache, but resolving the operator’s opt-out and missingCARGO_TARGET_DIRfirst — the same two checkshousekeep’s idle pass makes before ever measuring the cache, factored out socrate::daemon’s between-runs check (see the module’s own doc for why congestion can make “idle” arrive too rarely to matter) makes them identically rather than growing its own copy that could drift.Ok(None)covers a cap of0(see the module docs oncache_limit_bytes), a config that renders noCARGO_TARGET_DIRto aggregate at all, and a cache currently in use (seeprune_cache).