R-361 follow-on: the undo-copy prune must run above the already-current check
gates / gates (push) Successful in 11s
gates / gates (push) Successful in 11s
Excluding pre-restore-* from db_dumps made that list stable across restores, so CaptureRecoveryUnit's already-current early return began firing where it never had - and the prune, which sat after it, stopped running in exactly the case it exists for. Measured on demo-hp minutes after the change: four undo copies on disk against a cap of three. The prune is housekeeping on the dump directory and is independent of whether the manifest needs rewriting, so it belongs above the check. Pruning cannot disturb dbDumps, which no longer contains those names. Pinned by TestR361_UndoCapHoldsWhenTheUnitIsAlreadyCurrent; its red-proof moves the call back below the return and the cap fails at 5.
This commit is contained in:
@@ -160,6 +160,20 @@ func (m *Manager) CaptureRecoveryUnit(stackName string) error {
|
||||
runID, dumpsAt = cur.OffsiteRunID, cur.DumpsAt
|
||||
}
|
||||
|
||||
// R-379/R-361: bound the undo copies BEFORE the already-current check, not after it.
|
||||
//
|
||||
// It used to sit at the end of this function, and that was fine only while `db_dumps` listed the
|
||||
// `pre-restore-*` files: a new undo copy changed the list, so the check below never short-circuited
|
||||
// and the prune always ran. R-361 excluded those files from `db_dumps` — correctly — and that made
|
||||
// the list STABLE across restores, so the early return began firing and the prune became
|
||||
// unreachable in exactly the case it exists for. Measured on demo-hp 2026-08-22: four undo copies
|
||||
// on disk against a cap of three, immediately after the change.
|
||||
//
|
||||
// It is housekeeping on the dump directory and has nothing to do with whether the manifest needs
|
||||
// rewriting, so it belongs above the check. Pruning cannot disturb `dbDumps`, which no longer
|
||||
// contains those names at all.
|
||||
m.pruneUndoCopies(AppDBDumpPath(nsRoot, stackName), stackName)
|
||||
|
||||
// Skip if the unit is already current — avoids needless drive writes on the periodic refresh.
|
||||
// The run-id is part of "current": an offsite run must re-stamp the manifest even when nothing
|
||||
// else changed, because the stamp is exactly the claim the restore path reads.
|
||||
@@ -215,7 +229,6 @@ func (m *Manager) CaptureRecoveryUnit(stackName string) error {
|
||||
// R-379: bound the undo copies. AFTER a successful capture and never before one — the capture is
|
||||
// the point at which nothing is depending on those files, whereas the restore path is precisely
|
||||
// where deleting one would remove the undo at the moment it is needed.
|
||||
m.pruneUndoCopies(AppDBDumpPath(nsRoot, stackName), stackName)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user