Review fixes for 0.340.0: C5 a catch-up releases the whole-guest backup when its backup legs end (red-proved); C3 the R-1187 c refusal text fits an unhealthy app; C6 two comments; C8 README backup.volumes wording; unreleased
gates / gates (push) Successful in 1m40s

This commit is contained in:
admin committed 2026-10-22 21:25:48 +02:00
1 parent 912e59210d
commit 943c517550
7 files changed
+57 -11

No files matched your search

+4 -2
View File
@@ -362,11 +362,13 @@ func (e *Exporter) executeImport(req ImportRequest, job *Job) {
// NOT running used to „overwrite config in place" — its volumes were never removed, and `docker cp` only adds and
// overwrites, so the result was the old data MERGED with the bundle's (a stale SQLite -wal beside the bundle's .db
// is a corruption shape), reported as success. Only a running app's volumes are removed first. So this import is
// refused here, before anything is written; the household starts the app (or removes it) and imports again.
// refused here, before anything is written; the household starts the app (or removes it) and imports again. „Not
// running" is IsStackRunning's view: running or degraded only, so an unhealthy or restarting app is refused too —
// the text says so and names removal (review 2026-10-22 night, C3; the import path for those states is R-1187).
// Pinned by TestR1187c_AStoppedAppIsNotImportedOver.
if isDeployed && !isRunning {
e.logger.Printf("[WARN] Import: refused — %s is installed but not running; importing over it would merge the old data with the bundle's (R-1187 c)", manifest.AppName)
e.failJob(job, step, "Az alkalmazás telepítve van, de nem fut, ezért a csomagot nem töltjük vissza: a régi adatai összekeveredhetnének a csomagéval. Az alkalmazás érintetlen. Indítsd el (vagy távolítsd el), és próbáld újra.")
e.failJob(job, step, "Az alkalmazás telepítve van, de nem fut rendben (leállt, vagy hibásan indul), ezért a csomagot nem töltjük vissza: a régi adatai összekeveredhetnének a csomagéval. Az alkalmazás érintetlen. Ha leállt, indítsd el; ha hibásan fut, távolítsd el. Utána próbáld újra.")
return
}
@@ -340,6 +340,13 @@ func (c *CatchUp) run(ctx context.Context, why string) {
names = append(names, string(leg))
}
c.Ledger.markCatchUp(c.now())
// The backup legs are done: the whole-guest backup no longer waits for this catch-up (review 2026-10-22 night, C5).
// The checks below read only the off-site store, and on a big store they take long — held, they could push that
// day's whole-guest backup out of its window. `pending` stays set until run() returns (no second catch-up).
// Pinned by TestC5_TheWholeGuestBackupDoesNotWaitForTheChecks.
c.mu.Lock()
c.running = false
c.mu.Unlock()
if c.After != nil {
c.Logger.Printf("[INFO] [catch-up] running the after-catch-up checks (the off-site proof and the due-gated integrity check, R-1189 d)")
c.After(ctx)
@@ -43,3 +43,29 @@ func TestR1189d_TheChecksRunAfterTheCatchUpLegs(t *testing.T) {
t.Fatal("no catch-up ran, so the after-catch-up checks must not run")
}
}
// C5 (review 2026-10-22 night): while the after-catch-up checks run, the catch-up no longer reports Running() — the
// scheduled whole-guest backup (quiesce.go, R-871) waits only for the backup legs, not for the off-site proof and the
// integrity check, which take long on a big store. RED-PROOF: with the `c.running = false` before After removed,
// this fails — seen failing 2026-10-22 night.
func TestC5_TheWholeGuestBackupDoesNotWaitForTheChecks(t *testing.T) {
h := newHarness(t, at(1, 12, 0), at(5, 9, 0))
h.l.MarkEnded(LegDBDump, at(4, 2, 31))
h.l.MarkEnded(LegTier2, at(4, 3, 31))
h.l.MarkEnded(LegOffsite, at(4, 4, 20))
var mu sync.Mutex
runningDuringAfter := []bool{}
h.c.After = func(context.Context) {
r := h.c.Running()
mu.Lock()
runningDuringAfter = append(runningDuringAfter, r)
mu.Unlock()
}
h.c.Evaluate(context.Background(), "start")
h.wait(t)
mu.Lock()
defer mu.Unlock()
if len(runningDuringAfter) != 1 || runningDuringAfter[0] {
t.Fatalf("Running() during the after-catch-up checks = %v, want [false]", runningDuringAfter)
}
}
+1 -1
View File
@@ -597,7 +597,7 @@ func (m *Manager) ClassifiedBinds(name string) ([]appbackup.ClassifiedBind, bool
return appbackup.ClassifyBinds(meta.Backup, binds)
}
// ExcludedDockerVolumes returns the Docker names of the stack's named volumes its template excludes from every backup
// ExcludedDockerVolumes returns the Docker names of the stack's named volumes its template excludes from every app-data backup
// (R-49, D21 = B; appbackup.ExcludedDockerVolumes), and a sentence per template entry that was ignored.
func (m *Manager) ExcludedDockerVolumes(name string) ([]string, []string) {
stack, ok := m.GetStack(name)