package natsjsregistry import ( "encoding/json" "errors" "strings" natsjskv "github.com/go-micro/plugins/v4/store/nats-js-kv" "github.com/nats-io/nats.go" "go-micro.dev/v4/registry" ) // NatsWatcher is the watcher of the nats interface type NatsWatcher interface { WatchAll(bucket string, opts ...nats.WatchOpt) (<-chan *natsjskv.StoreUpdate, func() error, error) } // Watcher is used to keep track of changes in the registry type Watcher struct { updates <-chan *natsjskv.StoreUpdate stop func() error reg *storeregistry } // NewWatcher returns a new watcher func NewWatcher(s *storeregistry) (*Watcher, error) { w, ok := s.store.(NatsWatcher) if !ok { return nil, errors.New("store does not implement watcher interface") } watcher, stop, err := w.WatchAll("service-registry") if err != nil { return nil, err } return &Watcher{ updates: watcher, stop: stop, reg: s, }, nil } // Next returns the next result. It is a blocking call func (w *Watcher) Next() (*registry.Result, error) { kve := <-w.updates if kve == nil { return nil, errors.New("watcher stopped") } var svc registry.Service if kve.Value.Data == nil { // fake a service parts := strings.SplitN(kve.Value.Key, _serviceDelimiter, 3) if len(parts) != 3 { return nil, errors.New("invalid service key") } svc.Name = parts[0] // OpenCloud registers nodes with a - separator svc.Nodes = []*registry.Node{{Id: parts[0] + "-" + parts[1]}} svc.Version = parts[2] } else { if err := json.Unmarshal(kve.Value.Data, &svc); err != nil { _ = w.stop() return nil, err } } return ®istry.Result{ Service: &svc, Action: kve.Action, }, nil } // Stop stops the watcher func (w *Watcher) Stop() { _ = w.stop() }