R-1348: the mail of an interrupted put-back names a restore, not an off-site run (seen on the live proof); changelog: R-1347, R-1348 proven live on 9202. Commit only.
gates / gates (push) Successful in 32s
gates / gates (push) Successful in 32s
This commit is contained in:
1 parent
c4b6844d34
commit
37644458c7
4 files changed
+40
-7
No files matched your search
+6
-1
@@ -16,7 +16,12 @@ skipped it until the controller restarted. New seam `backup.SetUpdateHeldForgett
|
|||||||
**R-1348 — a failed put-back at start-up mails the operator.** `holdPutBackFailed` writes the D20 hold at `Recover`, before any
|
**R-1348 — a failed put-back at start-up mails the operator.** `holdPutBackFailed` writes the D20 hold at `Recover`, before any
|
||||||
notifier exists, so only the hold reporter's info and the hub's later reminder said anything. `AppStopGuard.SetHeldNotify`
|
notifier exists, so only the hold reporter's info and the hub's later reminder said anything. `AppStopGuard.SetHeldNotify`
|
||||||
hands over what `Recover` held, once, and mails a later failure (a drive that returned) at once: the R-1340 sentence for
|
hands over what `Recover` held, once, and mails a later failure (a drive that returned) at once: the R-1340 sentence for
|
||||||
`MixedCauseInterruptedPutBack`, from the hold record. Tests `TestR1348_*`.
|
`MixedCauseInterruptedPutBack`, from the hold record. The mail's run name says „restore" for it, not „offsite-reconstitute"
|
||||||
|
(`heldRunKind`, seen on the live proof). Tests `TestR1348_*`. **Live proof 2026-11-03, scratch 9202, test image of c4b6844** (felhom.eu
|
||||||
|
`audits/security-2026-11-02/part3/`): a restore cut at „the restore copy is recorded", the volume held by a created-only
|
||||||
|
container, the controller started: hold `restore_mixed` / `interrupted_put_back`, the event `backup_run_failures` with the sentence in the sink.
|
||||||
|
**R-1347's live proof, same image:** an update with its undo copy cut off → hold `update_failed`; the household's restore → „the update hold is CLEARED", „its
|
||||||
|
update-held flag is forgotten"; six `kill -9` → the crash-loop watcher stops the app (`unhealthy_stop`), so it watches again.
|
||||||
|
|
||||||
**R-1339 — no false „drive … not mounted".** A per-app folder under a mounted drive is never a mountpoint itself; nine false lines
|
**R-1339 — no false „drive … not mounted".** A per-app folder under a mounted drive is never a mountpoint itself; nine false lines
|
||||||
at every start on 9202. The folder still gets no bind and no skeleton of its own (the row's „not skipped" would write a
|
at every start on 9202. The folder still gets no bind and no skeleton of its own (the row's „not skipped" would write a
|
||||||
|
|||||||
@@ -78,6 +78,16 @@ func heldStoppedOperatorText(h settings.RestoreHold) (msg, leg, reason string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// heldRunKind names the run in the mail's subject. A hold that does not say which restore wrote it is an off-site one, the
|
||||||
|
// pre-R-1340 rule, EXCEPT an interrupted put-back: its record names no kind, and its restore may be either, so „restore" (R-1348,
|
||||||
|
// seen live 2026-11-03: a local restore's mail read „offsite-reconstitute"). Pinned by TestR1348_HeldRunKind.
|
||||||
|
func heldRunKind(h settings.RestoreHold) string {
|
||||||
|
if h.RestoreKind == settings.RestoreKindLocal || h.MixedCause == settings.MixedCauseInterruptedPutBack {
|
||||||
|
return "restore"
|
||||||
|
}
|
||||||
|
return "offsite-reconstitute"
|
||||||
|
}
|
||||||
|
|
||||||
func mixedHoldText(h settings.RestoreHold, kind, tail string) (msg, leg, reason string) {
|
func mixedHoldText(h settings.RestoreHold, kind, tail string) (msg, leg, reason string) {
|
||||||
stack := h.Stack
|
stack := h.Stack
|
||||||
leg = "restore-hold-mixed"
|
leg = "restore-hold-mixed"
|
||||||
|
|||||||
@@ -1560,11 +1560,7 @@ func main() {
|
|||||||
holdNotify := func(stack string, replayErr, rollbackErr error) {
|
holdNotify := func(stack string, replayErr, rollbackErr error) {
|
||||||
h := heldHoldFromNotify(sett.GetRestoreHold, stack, replayErr, rollbackErr)
|
h := heldHoldFromNotify(sett.GetRestoreHold, stack, replayErr, rollbackErr)
|
||||||
msg, leg, reason := heldStoppedOperatorText(h)
|
msg, leg, reason := heldStoppedOperatorText(h)
|
||||||
runKind := "offsite-reconstitute"
|
d := notify.BackupRunFailuresDetails{RunKind: heldRunKind(h), Failed: 1, Attempted: 1}
|
||||||
if h.RestoreKind == settings.RestoreKindLocal {
|
|
||||||
runKind = "restore"
|
|
||||||
}
|
|
||||||
d := notify.BackupRunFailuresDetails{RunKind: runKind, Failed: 1, Attempted: 1}
|
|
||||||
d.Apps = append(d.Apps, notify.RunFailureDetail{App: stack, Leg: leg, Reason: reason})
|
d.Apps = append(d.Apps, notify.RunFailureDetail{App: stack, Leg: leg, Reason: reason})
|
||||||
notifier.NotifyBackupRunFailures(msg, d)
|
notifier.NotifyBackupRunFailures(msg, d)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
||||||
|
)
|
||||||
|
|
||||||
// R-1347 and R-1348: each seam is CALLED from main.go (an AST walk) — a seam built and never wired is the project's
|
// R-1347 and R-1348: each seam is CALLED from main.go (an AST walk) — a seam built and never wired is the project's
|
||||||
// oldest shape.
|
// oldest shape.
|
||||||
@@ -17,3 +21,21 @@ func TestR1348_HeldNotifyIsWiredAtStartup(t *testing.T) {
|
|||||||
t.Fatal("main.go never calls SetHeldNotify — a failed put-back at start-up would mail nobody")
|
t.Fatal("main.go never calls SetHeldNotify — a failed put-back at start-up would mail nobody")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The mail's run name for an interrupted put-back. RED (2026-11-03, live on 9202): the sink showed run_kind offsite-reconstitute for a
|
||||||
|
// local restore.
|
||||||
|
func TestR1348_HeldRunKind(t *testing.T) {
|
||||||
|
for _, c := range []struct {
|
||||||
|
h settings.RestoreHold
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{settings.RestoreHold{Reason: settings.HoldReasonRestoreMixed, MixedCause: settings.MixedCauseInterruptedPutBack}, "restore"},
|
||||||
|
{settings.RestoreHold{RestoreKind: settings.RestoreKindLocal}, "restore"},
|
||||||
|
{settings.RestoreHold{RestoreKind: settings.RestoreKindOffsite}, "offsite-reconstitute"},
|
||||||
|
{settings.RestoreHold{Reason: settings.HoldReasonRestoreMixed}, "offsite-reconstitute"},
|
||||||
|
} {
|
||||||
|
if got := heldRunKind(c.h); got != c.want {
|
||||||
|
t.Errorf("%+v: run kind %q, want %q", c.h, got, c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user