//go:build integration package process_test import ( "context" "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" ) // A module whose consumer the bus makes after the module started is not lost for that order: the hub tries again after // each wait and calls live once it is bound (the checker's "until it starts again" hole). func TestTheHubBindsALateConsumerAndSaysItIsLive(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.WithTimeout(context.Background(), 30*time.Second) defer cancel() if _, err := js.CreateStream(ctx, jetstream.StreamConfig{Name: process.EventsStream, Subjects: []string{"mesh.mod.*.event.>"}}); err != nil { t.Fatal(err) } cred := process.Account{Node: "n1", Module: "late"} hub := process.NewEventHub(t.Logf) waits, live := make(chan chan bool), make(chan struct{}, 1) wait := func(ctx context.Context) bool { step := make(chan bool) select { case waits <- step: case <-ctx.Done(): return false } return <-step } if err := hub.StartUntilBound(ctx, js, cred, wait, func() { live <- struct{}{} }); err == nil { t.Fatal("no consumer was there, and the start said nothing") } select { case <-live: t.Fatal("live before the consumer was there") default: } step := <-waits step <- true // tried again: still no consumer step = <-waits if _, err := js.CreateOrUpdateConsumer(ctx, process.EventsStream, jetstream.ConsumerConfig{Durable: cred.EventConsumerName(), AckPolicy: jetstream.AckExplicitPolicy}); err != nil { t.Fatal(err) } step <- true select { case <-live: case <-ctx.Done(): t.Fatal("the consumer was made and the hub never said it is live") } hub.Stop() }