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  }