gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/router/service/watcher.go (about)

     1  package service
     2  
     3  import (
     4  	"io"
     5  	"sync"
     6  	"time"
     7  
     8  	"gitee.com/liuxuezhan/go-micro-v1.18.0/router"
     9  	pb "gitee.com/liuxuezhan/go-micro-v1.18.0/router/proto"
    10  )
    11  
    12  type watcher struct {
    13  	sync.RWMutex
    14  	opts    router.WatchOptions
    15  	resChan chan *router.Event
    16  	done    chan struct{}
    17  }
    18  
    19  func newWatcher(rsp pb.Router_WatchService, opts router.WatchOptions) (*watcher, error) {
    20  	w := &watcher{
    21  		opts:    opts,
    22  		resChan: make(chan *router.Event),
    23  		done:    make(chan struct{}),
    24  	}
    25  
    26  	go func() {
    27  		for {
    28  			select {
    29  			case <-w.done:
    30  				return
    31  			default:
    32  				if err := w.watch(rsp); err != nil {
    33  					w.Stop()
    34  					return
    35  				}
    36  			}
    37  		}
    38  	}()
    39  
    40  	return w, nil
    41  }
    42  
    43  // watchRouter watches router and send events to all registered watchers
    44  func (w *watcher) watch(stream pb.Router_WatchService) error {
    45  	defer stream.Close()
    46  
    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  			Type:      router.EventType(resp.Type),
    69  			Timestamp: time.Unix(0, resp.Timestamp),
    70  			Route:     route,
    71  		}
    72  
    73  		select {
    74  		case w.resChan <- event:
    75  		case <-w.done:
    76  		}
    77  	}
    78  
    79  	return watchErr
    80  }
    81  
    82  // Next is a blocking call that returns watch result
    83  func (w *watcher) Next() (*router.Event, error) {
    84  	for {
    85  		select {
    86  		case res := <-w.resChan:
    87  			switch w.opts.Service {
    88  			case res.Route.Service, "*":
    89  				return res, nil
    90  			default:
    91  				continue
    92  			}
    93  		case <-w.done:
    94  			return nil, router.ErrWatcherStopped
    95  		}
    96  	}
    97  }
    98  
    99  // Chan returns event channel
   100  func (w *watcher) Chan() (<-chan *router.Event, error) {
   101  	return w.resChan, nil
   102  }
   103  
   104  // Stop stops watcher
   105  func (w *watcher) Stop() {
   106  	w.Lock()
   107  	defer w.Unlock()
   108  
   109  	select {
   110  	case <-w.done:
   111  		return
   112  	default:
   113  		close(w.done)
   114  	}
   115  }