docs(cache): state the .publish-* gap as a ticket, not a present state
The contract block asserted that neither side reclaims .publish-new- 'today'. True when written and about to stop being true: gitdan#30 tracks adding both .publish-* prefixes to the arbiter's enumeration, and a sibling track is landing it this round. A comment that dates itself against a merge in flight is worse than no comment. Rewords all four sites (cache-lib.sh, publish-snapshot.sh, and README's table row and prose) to reference gitdan#30 and keep the mechanism that made the shape worth catching — .publish-new- is tagged per job per run exactly as .stage- is — rather than the arbiter's momentary contents. The rule itself is unchanged; it is the durable part, and it is what found this. Adds the counting check while there: the five names here and the prefixes ci-cache-reclaim.sh enumerates are meant to be the same length, so a mismatch is the cheapest signal that one side gained a shape without telling the other.
This commit is contained in:
@@ -245,7 +245,7 @@ block is the canonical description; this side owns the names.
|
|||||||
| name | produced by | if the job dies holding it |
|
| name | produced by | if the job dies holding it |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `.stage-<tag>` | `cache-lib.sh`, `hardlink_clone_into()` | stranded; only the arbiter reclaims it |
|
| `.stage-<tag>` | `cache-lib.sh`, `hardlink_clone_into()` | stranded; only the arbiter reclaims it |
|
||||||
| `.publish-new-<tag>` | `publish-snapshot.sh` | stranded, and not in the arbiter's list |
|
| `.publish-new-<tag>` | `publish-snapshot.sh` | stranded; see `daniel/gitdan#30` |
|
||||||
| `.publish-old-<key>-<tag>` | `publish-snapshot.sh` | swept by the next publish of that key |
|
| `.publish-old-<key>-<tag>` | `publish-snapshot.sh` | swept by the next publish of that key |
|
||||||
| `.evicting-<name>-<pid>` | `prune-cache.sh`, `evict_dir()` | swept at the start of the next prune pass |
|
| `.evicting-<name>-<pid>` | `prune-cache.sh`, `evict_dir()` | swept at the start of the next prune pass |
|
||||||
| `.reading-<source>-<tag>` | `cache-lib.sh`, `reader_lock_acquire()` | not garbage — see below |
|
| `.reading-<source>-<tag>` | `cache-lib.sh`, `reader_lock_acquire()` | not garbage — see below |
|
||||||
@@ -263,8 +263,15 @@ renaming one. That script enumerates by explicit prefix rather than by dotglob
|
|||||||
stream alongside the trees they protect — so a name it has not been told about
|
stream alongside the trees they protect — so a name it has not been told about
|
||||||
is not handled conservatively, it is invisible, and an unreclaimed staging tree
|
is not handled conservatively, it is invisible, and an unreclaimed staging tree
|
||||||
is a full clone of a multi-GB target dir on the one volume whose entire problem
|
is a full clone of a multi-GB target dir on the one volume whose entire problem
|
||||||
is disk. `.publish-new-` is the standing example: it strands exactly as
|
is disk. `.publish-new-` is the worked example: the two `.publish-*` names were
|
||||||
`.stage-` does and is in neither side's sweep.
|
outside the contract when it was written, and `.publish-new-` strands exactly
|
||||||
|
as `.stage-` does, so it is the one that needed catching. Bringing both under
|
||||||
|
the arbiter's enumeration is tracked as `daniel/gitdan#30`.
|
||||||
|
|
||||||
|
The two lists are meant to be the same length — the five names above, and the
|
||||||
|
prefixes `ci-cache-reclaim.sh` enumerates. A mismatch means one side gained a
|
||||||
|
shape without telling the other, which is the drift the rule exists to catch
|
||||||
|
and the cheapest thing to check.
|
||||||
|
|
||||||
**The staleness constants are part of the same contract, and that half has a
|
**The staleness constants are part of the same contract, and that half has a
|
||||||
direction.** `CACHE_READ_STALE_SECONDS` (`cache-lib.sh`) and
|
direction.** `CACHE_READ_STALE_SECONDS` (`cache-lib.sh`) and
|
||||||
|
|||||||
+11
-6
@@ -55,12 +55,17 @@
|
|||||||
# is invisible: an unreclaimed staging tree is a full clone of a multi-GB
|
# is invisible: an unreclaimed staging tree is a full clone of a multi-GB
|
||||||
# target dir on the one volume whose entire problem is disk.
|
# target dir on the one volume whose entire problem is disk.
|
||||||
#
|
#
|
||||||
# Of the five above, the arbiter enumerates `.stage-`, `.evicting-` and
|
# The two `.publish-*` names predate the contract and were outside it when this
|
||||||
# `.reading-`. The two `.publish-*` names predate the contract and are not in
|
# block was written — the rule catching an uncovered shape on its first
|
||||||
# it, which is why `.publish-new-` — tagged per job per run exactly as
|
# application. `.publish-new-` is the one that mattered: it is tagged per job
|
||||||
# `.stage-` is — is a shape neither side reclaims today. Closing that is a
|
# per run exactly as `.stage-` is, so a publisher killed before the swap
|
||||||
# change over there, not here; the rule above is what stops the list growing
|
# strands a tree under a name no later run of that script matches, which is
|
||||||
# another one.
|
# precisely the shape only the arbiter can reach. Bringing both in is tracked
|
||||||
|
# as daniel/gitdan#30.
|
||||||
|
#
|
||||||
|
# The two lists are meant to be the same length. A shape here without a prefix
|
||||||
|
# there is one side having changed without telling the other, and it is
|
||||||
|
# cheapest to notice by counting.
|
||||||
#
|
#
|
||||||
# The two staleness constants the arbiter mirrors are part of the same
|
# The two staleness constants the arbiter mirrors are part of the same
|
||||||
# contract, and that half has a direction to it — see CACHE_READ_STALE_SECONDS
|
# contract, and that half has a direction to it — see CACHE_READ_STALE_SECONDS
|
||||||
|
|||||||
@@ -55,12 +55,13 @@ DST=$(snapshot_dir_for "$ROOT" "$OWN_KEY")
|
|||||||
# `.publish-old-` and `.publish-new-` are dot-prefixed names under a cache
|
# `.publish-old-` and `.publish-new-` are dot-prefixed names under a cache
|
||||||
# root, so the cross-repo contract at the top of cache-lib.sh covers them:
|
# root, so the cross-repo contract at the top of cache-lib.sh covers them:
|
||||||
# renaming either, or adding a third, requires a matching prefix in
|
# renaming either, or adding a third, requires a matching prefix in
|
||||||
# daniel/gitdan's ci-cache-reclaim.sh. Neither is in its list today, and
|
# daniel/gitdan's ci-cache-reclaim.sh. Both were outside its list when that
|
||||||
# `.publish-new-` is the shape that most needs to be — it is tagged per job per
|
# contract was written, and `.publish-new-` is why it mattered: it is tagged
|
||||||
# run, so a publisher killed between staging its snapshot and the swap below
|
# per job per run, so a publisher killed between staging its snapshot and the
|
||||||
# strands a full hardlink clone that no later run of this script will ever
|
# swap below strands a full hardlink clone that no later run of this script
|
||||||
# match. `.publish-old-` is milder: the sweep further down reclaims it on the
|
# will ever match. `.publish-old-` is milder — the sweep further down reclaims
|
||||||
# next publish of the same key.
|
# it on the next publish of the same key. Bringing both under the arbiter's
|
||||||
|
# enumeration is tracked as daniel/gitdan#30.
|
||||||
OLD="${ROOT}/.publish-old-${OWN_KEY}-${TAG}"
|
OLD="${ROOT}/.publish-old-${OWN_KEY}-${TAG}"
|
||||||
SNAP_NAME=$(basename "$DST")
|
SNAP_NAME=$(basename "$DST")
|
||||||
GRACE="${CACHE_READ_GRACE_SECONDS}"
|
GRACE="${CACHE_READ_GRACE_SECONDS}"
|
||||||
|
|||||||
Reference in New Issue
Block a user