R-1342: a restore copy under the stable-start watch is not deletable (D62 gap); an app removed during the watch raises no alarm — tests red first; commit only
gates / gates (push) Successful in 31s

This commit is contained in:
admin committed 2026-10-29 11:16:13 +01:00
1 parent 6c72e3ff34
commit 652a690e5d
10 files changed
+231 -1

No files matched your search

+35 -1
View File
@@ -28,6 +28,9 @@ const (
RestoreCopyNeededHold = "hold" // the app is held (a failed put-back keeps its copy, D20) — support decides
RestoreCopyNeededPutBack = "putback" // a put-back waits for its drive (R-1251) or a cut restore names it (D22)
RestoreCopyNeededUnknown = "unknown" // the app-stop marker cannot be read: nothing is offered (fail closed)
// RestoreCopyNeededChecking (R-1342): the box still watches whether the restored app runs stably (up to 30 minutes
// after the restore, R-1270) — the copy is the way back if it does not.
RestoreCopyNeededChecking = "checking"
)
var (
@@ -119,7 +122,10 @@ func (m *Manager) RestoreCopies() []RestoreCopy {
continue
}
rc := RestoreCopy{App: app, Stamp: c.Name(), At: at, SizeBytes: dirSize(dir), Path: dir, Needed: needed}
if needed == "" {
if rc.Needed == "" && m.watchingCopy(dir) {
rc.Needed = RestoreCopyNeededChecking
}
if rc.Needed == "" {
rc.DeleteOn = at.Add(restoreCopyUnusedAge)
}
out = append(out, rc)
@@ -174,9 +180,37 @@ func (m *Manager) DeleteRestoreCopy(app, stamp string) (RestoreCopy, error) {
if found.Needed = m.restoreCopyNeededFor(app, named, ok); found.Needed != "" {
return *found, ErrRestoreCopyNeeded
}
if m.watching[found.Path] { // R-1342: under m.mu, the same lock the watch marks its copy under
found.Needed = RestoreCopyNeededChecking
return *found, ErrRestoreCopyNeeded
}
if err := os.RemoveAll(found.Path); err != nil {
return *found, fmt.Errorf("removing the restore copy %s: %w", found.Path, err)
}
_ = os.Remove(filepath.Dir(found.Path)) // the per-app folder, when it is now empty
return *found, nil
}
// setWatching marks (on) or clears a copy a stable-start watch holds (R-1342).
func (m *Manager) setWatching(dir string, on bool) {
if dir == "" {
return
}
m.mu.Lock()
defer m.mu.Unlock()
if on {
if m.watching == nil {
m.watching = map[string]bool{}
}
m.watching[dir] = true
return
}
delete(m.watching, dir)
}
// watchingCopy reports whether a stable-start watch still holds the copy.
func (m *Manager) watchingCopy(dir string) bool {
m.mu.Lock()
defer m.mu.Unlock()
return m.watching[dir]
}