R-1270 (P2): a restore whose app does not reach running in time is never a success — every restore path returns ErrRestoreNotStarted, the household reads that the data is back but the app has not started yet, one operator alarm; the data stays, the undo copy is kept, a late start turns the record into a success and releases the copy. Red-proved. Commit only.
gates / gates (push) Successful in 1m32s

This commit is contained in:
2026-10-25 09:33:26 +01:00
parent 02daebe9c5
commit b680db85cb
18 changed files with 405 additions and 23 deletions
+6 -4
View File
@@ -2,6 +2,7 @@ package backup
import (
"context"
"errors"
"fmt"
"gitea.dooplex.hu/admin/felhom-controller/internal/util"
"os"
@@ -241,7 +242,7 @@ func (m *Manager) RestoreTier2Unit(stackName string) (UnitRestoreResult, error)
// It is best-effort by design and says so in the log either way, because an absent log line is not
// evidence that it ran.
func (m *Manager) rehydratePrimaryUnit(stackName, mirrorUnitDir string, restoreErr error) {
if restoreErr != nil {
if restoreErr != nil && !errors.Is(restoreErr, ErrRestoreNotStarted) { // R-1270: the data DID land then
m.logger.Printf("[INFO] [backup] %s: primary unit NOT refilled — the restore itself failed (R-403: a package from a failed run is worse than none)", stackName)
return
}
@@ -440,9 +441,7 @@ func (m *Manager) RestoreTier2Files(stackName string) (filesRestored int, err er
if startErr != nil {
m.logger.Printf("[ERROR] [backup] failed to restart %s after Tier-2 file restore: %v", stackName, startErr)
}
if healthErr := m.waitForHealthy(stackName, healthTimeout); healthErr != nil {
m.logger.Printf("[WARN] [backup] %s Tier-2 file restore done but health check failed: %v", stackName, healthErr)
}
healthErr := m.waitForHealthy(stackName, healthTimeout)
if copyErr != nil {
return filesRestored, util.MsgError("err.backup.fajlmasolas_sikertelen", copyErr)
@@ -450,6 +449,9 @@ func (m *Manager) RestoreTier2Files(stackName string) (filesRestored int, err er
if startErr != nil {
return filesRestored, util.MsgError("err.backup.fajl_visszaallitva_de_az_alkalmazas_ujrainditasa", filesRestored, startErr)
}
if healthErr != nil { // R-1270: the files are back, the app is not — never a success
return filesRestored, m.restoreNotStarted(stackName, "second-drive file restore", healthErr, nil)
}
// Privacy: count + duration only — customer file names never at INFO.
m.logger.Printf("[INFO] [backup] Tier-2 file restore completed for %s: %d file(s) restored (%s)",
stackName, filesRestored, time.Since(start).Round(time.Second))