github.com/annwntech/go-micro/v2@v2.9.5/router/service/watcher.go (about) 1 package service 2 3 import ( 4 "io" 5 "sync" 6 "time" 7 8 "github.com/annwntech/go-micro/v2/router" 9 pb "github.com/annwntech/go-micro/v2/router/service/proto" 10 ) 11 12 type watcher struct { 13 sync.RWMutex 14 opts router.WatchOptions 15 resChan chan *router.Event 16 done chan struct{} 17 stream pb.Router_WatchService 18 } 19 20 func newWatcher(rsp pb.Router_WatchService, opts router.WatchOptions) (*watcher, error) { 21 w := &watcher{ 22 opts: opts, 23 resChan: make(chan *router.Event), 24 done: make(chan struct{}), 25 stream: rsp, 26 } 27 28 go func() { 29 for { 30 select { 31 case <-w.done: 32 return 33 default: 34 if err := w.watch(rsp); err != nil { 35 w.Stop() 36 return 37 } 38 } 39 } 40 }() 41 42 return w, nil 43 } 44 45 // watchRouter watches router and send events to all registered watchers 46 func (w *watcher) watch(stream pb.Router_WatchService) error { 47 var watchErr error 48 49 for { 50 resp, err := stream.Recv() 51 if err != nil { 52 if err != io.EOF { 53 watchErr = err 54 } 55 break 56 } 57 58 route := router.Route{ 59 Service: resp.Route.Service, 60 Address: resp.Route.Address, 61 Gateway: resp.Route.Gateway, 62 Network: resp.Route.Network, 63 Link: resp.Route.Link, 64 Metric: resp.Route.Metric, 65 } 66 67 event := &router.Event{ 68 Id: resp.Id, 69 Type: router.EventType(resp.Type), 70 Timestamp: time.Unix(0, resp.Timestamp), 71 Route: route, 72 } 73 74 select { 75 case w.resChan <- event: 76 case <-w.done: 77 } 78 } 79 80 return watchErr 81 } 82 83 // Next is a blocking call that returns watch result 84 func (w *watcher) Next() (*router.Event, error) { 85 for { 86 select { 87 case res := <-w.resChan: 88 switch w.opts.Service { 89 case res.Route.Service, "*": 90 return res, nil 91 default: 92 continue 93 } 94 case <-w.done: 95 return nil, router.ErrWatcherStopped 96 } 97 } 98 } 99 100 // Chan returns event channel 101 func (w *watcher) Chan() (<-chan *router.Event, error) { 102 return w.resChan, nil 103 } 104 105 // Stop stops watcher 106 func (w *watcher) Stop() { 107 w.Lock() 108 defer w.Unlock() 109 110 select { 111 case <-w.done: 112 return 113 default: 114 w.stream.Close() 115 close(w.done) 116 } 117 }