package main import ( "bytes" "context" "encoding/json" "testing" "time" "github.com/nats-io/nats.go/jetstream" "github.com/novox/mesh-controller/internal/broker" "github.com/novox/mesh-controller/internal/conditions" "github.com/novox/mesh-controller/internal/inventory" "github.com/novox/mesh-controller/internal/testbus" ) // **Looks at an unchanged condition write the bucket once, and `conditions` still says how often and when // it was seen** (novox/hq issue 420): the looks are in the controller's store, and the verb, run as a // process of its own, reads them from there. On 2026-10-10 one open condition had rewritten the bucket 7 003 // times in two days. func TestTheConditionsVerbReadsTheLooksTheBucketNoLongerHolds(t *testing.T) { inv := inventory.ForTest(t) bus := testbus.Start(t) serving, err := broker.Dial(bus.ClientURL()) if err != nil { t.Fatal(err) } defer serving.Close() if err := serving.EnsureControllerBuckets(); err != nil { t.Fatal(err) } ctx := t.Context() store, history, err := conditions.OnTheBus(ctx, serving.Conn()) if err != nil { t.Fatal(err) } k := conditions.NewKeeper(ctx, conditions.Options{Store: store, History: history, Looks: storeLooks{inv}}) defer k.Close(context.Background()) look := conditions.Observation{Scope: conditions.ScopeMachine, ID: "anchor", Kind: "silent", Machine: "anchor", Severity: conditions.Warning, Summary: "anchor has not been heard from", Source: "S1"} for range 4 { if _, err := k.Observe(ctx, look); err != nil { t.Fatal(err) } } api, err := jetstream.New(serving.Conn()) if err != nil { t.Fatal(err) } stream, err := api.Stream(ctx, "KV_"+broker.ConditionsBucket) if err != nil { t.Fatal(err) } info, err := stream.Info(ctx) if err != nil { t.Fatal(err) } if info.State.LastSeq != 1 { t.Fatalf("four looks at one unchanged condition wrote the bucket %d times, want 1", info.State.LastSeq) } // The verb as a process other than the serving controller: it reads the bucket and the store. keptBefore := conditionsFrom conditionsFrom = nil defer func() { conditionsFrom = keptBefore }() t.Setenv(broker.NATSVar, bus.ClientURL()) t.Setenv(broker.CertificateVar, "") var shown bytes.Buffer if err := showCondition(ctx, []string{"machine.anchor.silent", "--json"}, &shown); err != nil { t.Fatal(err) } var c conditions.Condition if err := json.Unmarshal(shown.Bytes(), &c); err != nil { t.Fatalf("%v: %s", err, shown.String()) } if c.Observations != 4 || len(c.Evidence) != 4 || c.LastObserved.IsZero() || c.LooksUnread != "" || time.Since(c.LastObserved) > time.Minute { t.Fatalf("conditions show reads %d observation(s), %d evidence line(s), last %s (%q)", c.Observations, len(c.Evidence), c.LastObserved, c.LooksUnread) } listed, err := openConditions(ctx) if err != nil || len(listed) != 1 || listed[0].Observations != 4 { t.Fatalf("conditions lists %+v: %v", listed, err) } }