burn-down night watches: R-872 05:00 run worked as designed but silently (Tester 2 34.8 h old) — early returns now log why, check re-dated 2026-10-07; R-887: 2 lost jobs, both re-run green; session report
gates / gates (push) Successful in 2m17s
gates / gates (push) Successful in 2m17s
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:
@@ -1,3 +1,7 @@
|
||||
## unreleased
|
||||
|
||||
- **Fixed without a row (R-872 night watch):** the 05:00 deadline check's down-box judgement returned early in silence for a box never bound or first seen under 48 h ago, so the log read only „1 skipped (down)" and a night watch could not tell „too young to judge" from „judged, nothing missed". Each early return now logs why. `TestR872_DownButTooYoungIsLogged`; red-proved (without the line: the test fails).
|
||||
|
||||
## v0.138.0 — secrets sealed at rest, a cookie no sibling can plant, the box's own claim state, agent-binary drift (burn-down night: R-879, R-136, R-283, R-349, R-276) (2026-10-05)
|
||||
|
||||
**Operator action on deploy: log in again once** (the session cookie is renamed). **Roll-back needs one extra step
|
||||
|
||||
@@ -346,11 +346,21 @@ const (
|
||||
// expected_dbdump_missed and one expected_backup_missed, each only past its longer line, and never for a box that
|
||||
// was bound or first reported less than downDumpMissedAfter ago (nothing has been expected yet).
|
||||
func judgeDownCustomer(s *store.Store, id string, now time.Time, onEvent EventNotifyFunc, logger *log.Logger) (backupMissed, dbdumpMissed int) {
|
||||
// Each early return says so in the log: the 2026-10-06 05:00 night watch saw only "1 skipped (down)" and could not
|
||||
// tell "judged, nothing missed" from "too young to judge" (Tester 2, first report 34.8 h before). Pinned by
|
||||
// TestR872_DownButTooYoungIsLogged.
|
||||
if bound, err := s.HasEverBoundHost(id); err == nil && !bound {
|
||||
logger.Printf("[INFO] Deadline check: %s is DOWN — not judged: no host was ever bound", id)
|
||||
return 0, 0
|
||||
}
|
||||
first, ferr := s.GetFirstHostReportAt(id)
|
||||
if ferr != nil || first.IsZero() || now.Sub(first) < downDumpMissedAfter {
|
||||
age := "unknown"
|
||||
if ferr == nil && !first.IsZero() {
|
||||
age = now.Sub(first).Round(time.Minute).String()
|
||||
}
|
||||
logger.Printf("[INFO] Deadline check: %s is DOWN — not judged yet: first host report %s ago (under %s, nothing expected yet)",
|
||||
id, age, downDumpMissedAfter)
|
||||
return 0, 0
|
||||
}
|
||||
raise := func(typ, msg string) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"database/sql"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -84,3 +85,15 @@ func TestR872_NewDownBoxIsQuiet(t *testing.T) {
|
||||
t.Fatalf("events %v for a box bound a day ago", got)
|
||||
}
|
||||
}
|
||||
|
||||
// The 2026-10-06 05:00 night watch saw only "1 skipped (down)" for Tester 2 (first report 34.8 h before) and could not
|
||||
// tell "too young to judge" from "judged, nothing missed": the early return wrote no line. Now it says which.
|
||||
// Red-proof: drop the Printf in judgeDownCustomer's age return → the line is missing.
|
||||
func TestR872_DownButTooYoungIsLogged(t *testing.T) {
|
||||
st, _, sc := downBox(t, 34*time.Hour)
|
||||
var buf strings.Builder
|
||||
CheckBackupDeadlines(st, sc, func(cid, et, sev, msg, det, src string) {}, log.New(&buf, "", 0))
|
||||
if !strings.Contains(buf.String(), "c1 is DOWN — not judged yet: first host report") {
|
||||
t.Fatalf("no 'not judged yet' line for a down box 34 h old; log:\n%s", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user