Second review of the night's own code: a stray clears when a later removal works (N2), the start-up check never removes this process's own copy (N3), one copy per destination at a time (N4), RunTier2 refuses during a restore for every caller (N5), the import refusal no longer advises removal (N9); red-proved, race-clean; README; REPORT; unreleased
gates / gates (push) Successful in 1m40s
gates / gates (push) Successful in 1m40s
This commit is contained in:
@@ -340,6 +340,12 @@ func (m *Manager) tier2ReconcileRoots(destBase string, roots, legRels []string)
|
||||
// capture legs (§8). Best-effort and idempotent. Records status for the UI; returns an error only on
|
||||
// an actual copy failure (no valid target is a recorded status, not an error).
|
||||
func (m *Manager) RunTier2(stackName string) error {
|
||||
// R-1180 for EVERY caller (review 2026-10-23 night, N5): the household's „Tier 2 on" save and the debug run call
|
||||
// this directly, outside RunAllTier2's skip — a mirror (rsync --delete) must never start during a restore of the app.
|
||||
if m.restoreRunningFor(stackName) {
|
||||
m.logger.Printf("[WARN] [backup] Tier 2 for %s not started — a restore of it is running; it is mirrored at the next run (R-1180)", stackName)
|
||||
return nil
|
||||
}
|
||||
// Customer turned Tier 2 off for this app (config panel) — skip without touching status.
|
||||
if m.settings != nil {
|
||||
if cd := m.settings.GetCrossDriveConfig(stackName); cd != nil && cd.UserDisabled {
|
||||
@@ -797,6 +803,10 @@ func rsyncMirror(src, dst string) error {
|
||||
s, d := strings.TrimRight(src, "/"), strings.TrimRight(dst, "/")
|
||||
rs := []string{"-a", "--delete", s + "/", d + "/"}
|
||||
name, app := tier2CopyName(d)
|
||||
// One copy per destination at a time in this process (review N4): a second run waits, it never removes the first.
|
||||
lk := tier2CopyLock(name)
|
||||
lk.Lock()
|
||||
defer lk.Unlock()
|
||||
tier2CopyBegin(app)
|
||||
defer tier2CopyEnd(app)
|
||||
if tier2CappedPath(s) && tier2CappedPath(d) {
|
||||
@@ -813,7 +823,9 @@ func rsyncMirror(src, dst string) error {
|
||||
// created empty — an empty source would let `--delete` empty the copy (review 2026-10-22 night, C4).
|
||||
"--mount", "type=bind,src=" + s + ",dst=" + s + ",readonly", "--mount", "type=bind,src=" + d + ",dst=" + d,
|
||||
"--entrypoint", "rsync", img}, rs...)
|
||||
tier2MarkRunning(name, true) // the start-up retry never removes a copy this process runs (review N3)
|
||||
out, code, err := tier2RunCapped(ctx, args)
|
||||
tier2MarkRunning(name, false)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user