feat: tatami gc — age-based reclamation across the global cache #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Add a
tatami gccommand that sweeps the global tatami cache (the user-levelroot that holds every pool, same scope as
prune --all) and reclaims idle,inactive slots that have aged past a threshold. Dry-run by default;
--yestoexecute;
--delete-older-than <duration>sets the age cutoff.Motivation
Neither existing reclamation command covers age-based cleanup of the whole cache:
pruneonly reclaims slots whose bound bookmark has landed on trunk(
src/prune.rsclassify). Anonymous or unlanded-but-abandoned work is neverswept, so
~/.tatamiaccumulates slots (and whole pools) for repos andbranches nobody has touched in months.
destroyis a deliberate, single-target (or single-pool) operation, not acache-wide sweep.
gcfills the gap: "reclaim disk from everything I clearly abandoned," keyed onage rather than merge status.
Semantics
A slot is a gc candidate when all of:
owner_alive) and no process cwd inside the slot(
process::is_slot_in_use). Reuse the exact idle testprune/destroyshare.prune).Escalation via a flag could allow leased removal later, but default skips.
--delete-older-than.Crucially, unlike
prune, gc does not require the bookmark to be merged intotrunk. It is age-based and will remove unlanded work, so it is genuinely
destructive. That is why dry-run is the default and
--yesis required toexecute (same contract as
prune/destroy).Flags
--delete-older-than <DURATION>— humantime-style duration (7d,24h,2w).Decide whether this is required or has a conservative default (e.g. no default =
must be explicit, since the operation is destructive).
--yes— execute the removal instead of the dry run.--verbose,-v— list each skipped slot with its reason (asprune -vdoes).--json/--toonstructured-output contract; a gc resultshould aggregate per pool like
PrunePool, reporting reclaimable/reclaimedbytes.
Open design questions
SlotEntryhascreated_at,leased_at,owner_started_at— but no last-used / last-returned timestamp. Keying gcon
created_atwould delete long-lived warm slots that are actively reused,which is wrong. Likely need a new
last_used_atfield stamped on acquire andon return, falling back to
created_at(or the workspace dir mtime) for slotspredating the field. This is the core prerequisite and should be settled first.
last slot is swept, and/or pools whose backing repo path no longer exists?
The "global cache" framing points at reclaiming entire dead pools, not just
slots.
(
--include-leased) mirroringdestroy, or leave leases strictly untouchable?pre_destroyhooks. gc should runpre_destroyper slotlike
prune/destroydo.Relationship to existing commands
prune= safe reclamation of landed work (merge-gated).destroy= deliberate, targeted removal.gc= cache-wide, age-gated reclamation of abandoned idle work, acceptingthat it may drop unlanded commits (hence dry-run default +
--yes).Implementation would live alongside
src/prune.rs/src/destroy.rsandsrc/cmd/, reusingprune_all's pool-discovery walk, the shared idle test, andremove_slot.