R-1256: four restore edges (review round 2 HUNT-1 H4/H5/H6/H8) — each test seen failing first
gates / gates (push) Successful in 31s
gates / gates (push) Successful in 31s
H4: a failed definition write in the off-site restore writes the live definition back before the start;
a failed write-back holds the app (restore_mixed).
H5: a put-back whose stop fails pours nothing, keeps the copy and holds the app (off-site, local, power-cut);
a failed definition write-back keeps the copy (D20); a failed 'volume rm -f' fails that volume (no merge).
H6: TryBeginRestoreOp/RestoreBusy: check every operation and record the restore in one step under m.mu;
every web handler and the kept loads begin through it; install-time kept load asks about the mirror too.
H8: SweepUnusedRestoreCopies every 6 h: removes a copy only with no hold, no marker naming it, no restore
running, and older than 14 days.
Commit only; rides the next controller release.
This commit is contained in:
1 parent
ed3927f03a
commit
342a394bff
20 files changed
+860
-50
No files matched your search
@@ -301,8 +301,12 @@ func (m *Manager) downloadKeptOffsiteUnit(ctx context.Context, app, drive string
|
||||
// LoadKeptOffsite is LoadKeptApp from the off-site copy c: download the unit alone, judge it, then
|
||||
// prepare (nil = nothing; a dated folder's files move back here), then the one unit restore, then
|
||||
// after(ok). A download failure or a refusal never reaches prepare, so the kept files stay as they were.
|
||||
func (m *Manager) LoadKeptOffsite(app, drive string, c KeptCopy, prepare func() error, okMsg, failMsg func(err error) string, after func(ok bool)) {
|
||||
m.BeginRestoreOp("restore", app)
|
||||
// ErrRestoreBusy (nothing started, after not called) when another operation runs (R-1256 H6).
|
||||
func (m *Manager) LoadKeptOffsite(app, drive string, c KeptCopy, prepare func() error, okMsg, failMsg func(err error) string, after func(ok bool)) error {
|
||||
if busy, _ := m.TryBeginRestoreOp("restore", app); busy != "" {
|
||||
m.logger.Printf("[WARN] [backup] kept load %s REFUSED: a %s operation runs (R-1256)", app, busy)
|
||||
return ErrRestoreBusy
|
||||
}
|
||||
go func() {
|
||||
start := time.Now()
|
||||
fail := func(err error) {
|
||||
@@ -345,6 +349,7 @@ func (m *Manager) LoadKeptOffsite(app, drive string, c KeptCopy, prepare func()
|
||||
after(true)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemovedUnitOnDrive is the start-fresh hook (stacks.SetKeptUnitFinder): the removed app's OWN unit when
|
||||
@@ -370,11 +375,26 @@ func (m *Manager) PrimaryUnitHome(app, drive string) string {
|
||||
|
||||
// LoadKeptApp runs the load as a restore operation the backup pages already follow (the poll banner):
|
||||
// Begin → RestoreFromRecoveryUnitAt(app, unitDir) → End, then after(ok) in the same goroutine (the
|
||||
// after_load command, the kept folder's tidy-up). The caller has checked RestoreStatus/IsRunning.
|
||||
func (m *Manager) LoadKeptApp(app, unitDir string, okMsg, failMsg func(err error) string, after func(ok bool)) {
|
||||
m.BeginRestoreOp("restore", app)
|
||||
// after_load command, the kept folder's tidy-up). prepare (nil = nothing) runs first, inside the operation — a dated
|
||||
// folder's files move back there. R-1256 H6: the op is begun in the same step as the check for every other operation;
|
||||
// a refusal returns ErrRestoreBusy with nothing started and nothing moved.
|
||||
func (m *Manager) LoadKeptApp(app, unitDir string, prepare func() error, okMsg, failMsg func(err error) string, after func(ok bool)) error {
|
||||
if busy, _ := m.TryBeginRestoreOp("restore", app); busy != "" {
|
||||
m.logger.Printf("[WARN] [backup] kept load %s REFUSED: a %s operation runs (R-1256)", app, busy)
|
||||
return ErrRestoreBusy
|
||||
}
|
||||
go func() {
|
||||
start := time.Now()
|
||||
if prepare != nil {
|
||||
if perr := prepare(); perr != nil {
|
||||
m.logger.Printf("[ERROR] [backup] kept load %s: preparing the kept files FAILED: %v — nothing was loaded", app, perr)
|
||||
m.EndRestoreOp(false, failMsg(perr))
|
||||
if after != nil {
|
||||
after(false)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
res, err := m.keptUnitRestore()(app, unitDir)
|
||||
if errors.Is(err, ErrRestoreNotStarted) {
|
||||
m.keptLoadNotStarted(app, err, after)
|
||||
@@ -395,6 +415,7 @@ func (m *Manager) LoadKeptApp(app, unitDir string, okMsg, failMsg func(err error
|
||||
after(true)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// keptLoadNotStarted (R-1270): the kept data is loaded but the app did not start in time. Never „done": the record says
|
||||
|
||||
Reference in new issue
Block a user