controller v0.265.0: R-634 cause fixed, held apps say so, OOM storm alarm, R-647 leftovers
gates / gates (push) Successful in 27s
gates / gates (push) Successful in 27s
R-634: a whole-box backup no longer stops/restarts a DEPLOYING app (the measured cause of containers running under 'not deployed'); StopStack and StartStack refuse a deploying stack for every caller. R-625: held badge 'Stopped - restore needed', no Update button. R-636: kernel oom_kill counter; 20+ in 30 min -> one app_oom_storm. R-647: held error per reader, copy_holds key, two log wordings. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -620,7 +620,7 @@ func main() {
|
||||
d.CopyDate = ev.CopyDate.UTC().Format(time.RFC3339)
|
||||
}
|
||||
if backupMgr != nil && ev.CopyTier > 0 {
|
||||
d.CopyHolds = backupMgr.UpdateCopyHolds(ev.App, ev.CopyTier)
|
||||
d.CopyHolds = backupMgr.UpdateCopyHoldsKey(ev.App, ev.CopyTier) // R-647: the key, never the Hungarian phrase
|
||||
}
|
||||
notifier.NotifyAppUpdateHeld(d, func(lang string) string {
|
||||
if ev.HoldRecorded && backupMgr != nil {
|
||||
@@ -851,8 +851,8 @@ func main() {
|
||||
logger.Printf("[WARN] [deadapp] OOM scan failed: %v", oerr)
|
||||
} else {
|
||||
for _, o := range ooms {
|
||||
logger.Printf("[WARN] [deadapp] %s: container %s was OOM-killed (started %s)", o.Stack, o.Container, o.StartedAt)
|
||||
notifier.NotifyAppOOM(o.Stack, o.Container, o.StartedAt)
|
||||
logger.Printf("[WARN] [deadapp] %s: container %s was OOM-killed (started %s; kills %d, limit %s, peak %s)", o.Stack, o.Container, o.StartedAt, o.Kills, o.MemLimit, o.Peak)
|
||||
notifier.NotifyAppOOM(o.Stack, o.Container, o.StartedAt, o.Kills, o.MemLimit, o.Peak)
|
||||
}
|
||||
}
|
||||
deadAppScans++
|
||||
@@ -2556,7 +2556,10 @@ func (a *stackAdapter) GetStackClassifiedBinds(name string) ([]backup.Classified
|
||||
func (a *stackAdapter) ListDeployedStacks() []backup.StackSummary {
|
||||
var result []backup.StackSummary
|
||||
for _, s := range a.mgr.GetStacks() {
|
||||
if !s.Deployed {
|
||||
// R-634 (v0.265.0): `Deployed` is set true in memory the moment a deploy is ACCEPTED (the
|
||||
// no-stale-button UX), so without the second test a deploy still pulling was in every backup
|
||||
// leg's list — and the volume leg stopped and restarted it in the middle of its own `up`.
|
||||
if !s.Deployed || s.Deploying {
|
||||
continue
|
||||
}
|
||||
result = append(result, backup.StackSummary{
|
||||
@@ -2574,6 +2577,13 @@ func (a *stackAdapter) StopStack(name string) error {
|
||||
return a.mgr.StopStack(name)
|
||||
}
|
||||
|
||||
// IsDeploying answers backup's optional deployingReporter (R-634): the volume leg asks it again
|
||||
// immediately before it stops an app, because its list is taken once at the start of the run.
|
||||
func (a *stackAdapter) IsDeploying(name string) bool {
|
||||
s, ok := a.mgr.GetStack(name)
|
||||
return ok && s.Deploying
|
||||
}
|
||||
|
||||
func (a *stackAdapter) StartStack(name string) error {
|
||||
return a.mgr.StartStack(name)
|
||||
}
|
||||
@@ -3471,6 +3481,14 @@ func (a *updateGuardsAdapter) HoldFor(name string) (bool, string) {
|
||||
return a.b.RestoreHoldFor(name)
|
||||
}
|
||||
|
||||
// HoldForLang renders the hold sentence for one reader (R-647, v0.265.0).
|
||||
func (a *updateGuardsAdapter) HoldForLang(name, lang string) (bool, string) {
|
||||
if a.b == nil {
|
||||
return false, ""
|
||||
}
|
||||
return a.b.RestoreHoldForLang(name, lang)
|
||||
}
|
||||
|
||||
func (a *updateGuardsAdapter) Busy(name string) (bool, string) {
|
||||
if a.q.SuppressedStacks()[name] {
|
||||
return true, "a whole-guest backup (quiesce) is holding it"
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// v0.264.0. The update-event sink and the R-646 backfill are both CALLED from main.go (an AST walk —
|
||||
// a comment naming them would not count). A sink built and never wired would fail silently: no event,
|
||||
@@ -21,3 +25,16 @@ func TestUpdateEventSinkIsWiredAtStartup(t *testing.T) {
|
||||
t.Error("BackfillAppliedMeta (R-646) must be called, after AdoptPins")
|
||||
}
|
||||
}
|
||||
|
||||
// R-647 (2) — the held event carries the copy_holds KEY, never the Hungarian phrase: the hub prints the
|
||||
// raw details as the household mail's `Note:` line. COMPANION RED-PROOF (REPORT.md): wire
|
||||
// UpdateCopyHolds back — this fails.
|
||||
func TestR647_HeldEventCarriesTheCopyHoldsKey(t *testing.T) {
|
||||
src, err := os.ReadFile("main.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(src), "d.CopyHolds = backupMgr.UpdateCopyHoldsKey(") {
|
||||
t.Fatal("main.go must fill AppUpdateDetails.CopyHolds with UpdateCopyHoldsKey (the key), not the Hungarian phrase")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user