package multi import ( "sync" "go-micro.dev/v4/registry" ) type multiWatcher struct { wo registry.WatchOptions w []registry.Watcher next chan *registry.Result stop chan bool } func newMultiWatcher(r []registry.Registry, opts ...registry.WatchOption) (registry.Watcher, error) { var wo registry.WatchOptions for _, o := range opts { o(&wo) } mw := &multiWatcher{ wo: wo, next: make(chan *registry.Result), stop: make(chan bool), } for _, wr := range r { w, err := wr.Watch(opts...) if err != nil { return nil, err } mw.w = append(mw.w, w) } return mw, nil } func (mw *multiWatcher) Next() (*registry.Result, error) { cerr := make(chan error) for _, wt := range mw.w { go func(w registry.Watcher) { r, err := w.Next() if err != nil && err != registry.ErrNotFound { cerr <- err } mw.next <- r }(wt) } for { select { case err := <-cerr: return nil, err case r, ok := <-mw.next: if !ok { return nil, registry.ErrWatcherStopped } nr := ®istry.Result{} *nr = *r return nr, nil case <-mw.stop: return nil, registry.ErrWatcherStopped } } } func (mw *multiWatcher) Stop() { var wg sync.WaitGroup wg.Add(len(mw.w)) for _, w := range mw.w { go func(w registry.Watcher) { w.Stop() wg.Done() }(w) } wg.Wait() select { case <-mw.stop: return default: close(mw.stop) } }