Files
mesh-catalog/modules/mesh-knowledge/cmd/mesh-knowledge/health_test.go
T
jschoubben c73641c117 CAT-K12: the health on the ledger names the source and the move's last check, and fails for what the ledger owes
Unhealthy, naming the cause, for a ledger or the verdicts' stream that does not answer, a head behind its history, an index behind
the ledger and a stream at its cap; the idle drafts, the parts waiting on the judge and the records the form-only check refused
are counted and leave it healthy. A part waiting more than 30 minutes is asked of the operator once, cleared when it is judged.

Issue 1966.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 12:21:51 +01:00

84 lines
3.6 KiB
Go

package main
import (
"strings"
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/buscalls"
)
// The health on the ledger (to-be 55 §1.1, AC56): it names where the records are served from and the move's last check, is
// unhealthy for a ledger or a stream that does not answer, a head behind its history, an index behind the ledger and a stream
// at its cap, and counts what waits on a person (an idle draft, a part waiting on the judge, a form-only check refused) without
// failing; a part waiting more than 30 minutes is asked of the operator once, and the ask clears when it is judged.
func TestTheHealthOnTheLedgerNamesTheSourceAndFailsForWhatTheLedgerOwes(t *testing.T) {
w, f := ledgerWorld(t)
ls := w.k.Store.(*ledgerStore)
if err := ls.BuildIndex(t.Context()); err != nil {
t.Fatal(err)
}
f.fill = buscalls.StreamFilled{Fill: buscalls.Fill{Count: 3, Bytes: 100, MaxBytes: 512 << 20}}
base := HealthAnswer{State: "healthy", Healthy: true, Why: "the database serves"}
ans := w.k.ledgerHealth(base)
if !ans.Healthy || !strings.Contains(ans.Why, "served from the ledger") || !strings.Contains(ans.Why, "search index holds") {
t.Fatalf("%+v", ans)
}
// Each thing the ledger owes, one at a time.
for name, c := range map[string]struct {
set func()
want string
}{
"a head behind": {func() {
f.lag = buscalls.Lagged{Instances: []buscalls.InstanceLag{{Instance: "decision/0290", History: 9, State: 7}}}
}, "behind their history"},
"a stream at a cap": {func() { f.fill.Bytes = f.fill.MaxBytes }, "at its cap"},
"a stream that does not answer": {func() { f.noFill = true }, "does not answer"},
} {
f.lag, f.noFill = buscalls.Lagged{}, false
f.fill = buscalls.StreamFilled{Fill: buscalls.Fill{Bytes: 100, MaxBytes: 512 << 20}}
c.set()
got := w.k.ledgerHealth(base)
if got.Healthy || !strings.Contains(got.Why, c.want) {
t.Errorf("%s: %+v", name, got)
}
}
f.lag, f.noFill, f.fill = buscalls.Lagged{}, false, buscalls.StreamFilled{}
// An index behind the ledger: a record the ledger holds and the index does not.
ls.index.mu.Lock()
ls.index.docsOf = map[Key][]string{}
ls.index.mu.Unlock()
if got := w.k.ledgerHealth(base); got.Healthy || !strings.Contains(got.Why, "behind the ledger") {
t.Errorf("an index behind: %+v", got)
}
_ = ls.BuildIndex(t.Context())
// What waits on a person is counted and leaves it healthy; a part waiting more than 30 minutes is asked once.
w.k.States.State(askedState).Put("decision.0300.abc", map[string]any{"part": "Context", "record": "ADR 0300", "at": w.clock.Add(-time.Hour)})
w.k.States.State(draftsState).Put("decision.0301", Draft{Kind: KindDecision, Number: 301, Author: "a@n", Touched: w.clock.AddDate(0, 0, -8)})
got := w.k.ledgerHealth(base)
if !got.Healthy || !strings.Contains(got.Why, "1 part(s) waiting") || !strings.Contains(got.Why, "1 draft(s) untouched") {
t.Fatalf("%+v", got)
}
w.k.ledgerHealth(base)
if len(w.told) != 1 {
t.Fatalf("the operator was asked %d times", len(w.told))
}
w.k.States.State(askedState).Delete("decision.0300.abc")
w.k.ledgerHealth(base)
if len(w.cleared) != 1 {
t.Fatalf("the ask was not cleared: %v", w.cleared)
}
}
// The records served from the database say so, and fail nothing.
func TestTheHealthOnTheDatabaseSaysSo(t *testing.T) {
db := newMemStore()
states := newFakeStates()
m := newMovableStore(db, newLedgerStore(newFakeLedger(t), states), states)
k := &KB{Store: m, States: states}
ans := k.ledgerHealth(HealthAnswer{State: "healthy", Healthy: true, Why: "the database serves"})
if !ans.Healthy || !strings.Contains(ans.Why, "served from the database") {
t.Fatalf("%+v", ans)
}
}