//go:build integration package views_test import ( "context" "encoding/json" "testing" "time" "github.com/nats-io/nats.go" "github.com/nats-io/nats.go/jetstream" "git.novox.be/novox/mesh-sdk/go/process" "git.novox.be/novox/mesh-sdk/go/testbus" "git.novox.be/novox/mesh-sdk/go/views" "git.novox.be/novox/mesh-sdk/go/views/viewstest" ) // An owner's change is an ordinary event on the shared events stream (novox/hq ADR 0635 ยง5): a reader that follows the // owner's state by its read tool hears it on the module's durable consumer of that stream, with no stream of the owner's, // and a message that is no views event goes to Other. func TestAReaderHearsAnOwnersChangesAsOrdinaryEvents(t *testing.T) { nc, err := nats.Connect(testbus.URL(t)) if err != nil { t.Fatal(err) } defer nc.Close() js, err := jetstream.New(nc) if err != nil { t.Fatal(err) } ctx, cancel := context.WithCancel(context.Background()) defer cancel() cred := process.Account{Node: "n1", Module: "reader"} kv := viewstest.Serve(t, ctx, js, nc, "o", "modules", "o.o_read_modules", cred.EventConsumerName()) if _, err := kv.Put(ctx, "a", []byte(`{"n":1}`)); err != nil { t.Fatal(err) } other := make(chan string, 1) r := &views.ProcessReader{Module: "reader", Other: func(m jetstream.Msg) { other <- m.Subject(); _ = m.Ack() }, Logf: t.Logf, Call: func(tool string, body any) (json.RawMessage, error) { raw, _ := json.Marshal(body) m, err := nc.Request("mesh.mod.o.call.o_read_modules.n0", raw, 5*time.Second) if err != nil { return nil, err } return m.Data, nil }} if _, err := r.Follow("o", "modules", "o.o_read_modules"); err != nil { t.Fatal(err) } r.Start(ctx, js, cred, nil) <-r.Ready() pic, err := r.KeyValue(ctx, "o_modules") if err != nil { t.Fatal(err) } w, err := pic.Watch(ctx, "b") if err != nil { t.Fatal(err) } if _, err := kv.Put(ctx, "b", []byte(`{"n":2}`)); err != nil { t.Fatal(err) } for e := range w.Updates() { if e != nil && e.Key() == "b" { break } } if s := r.Followers()[0].Status(); s.Asks != 1 || s.Keys != 2 { t.Fatalf("the change was not heard as an event alone: %+v", s) } if _, err := js.Publish(ctx, "mesh.mod.o.event.something-else", []byte("{}")); err != nil { t.Fatal(err) } if got := <-other; got != "mesh.mod.o.event.something-else" { t.Fatalf("other got %s", got) } }