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

     1  package router
     2  
     3  import (
     4  	"errors"
     5  	"sync"
     6  	"time"
     7  )
     8  
     9  var (
    10  	// ErrWatcherStopped is returned when routing table watcher has been stopped
    11  	ErrWatcherStopped = errors.New("watcher stopped")
    12  )
    13  
    14  // EventType defines routing table event
    15  type EventType int
    16  
    17  const (
    18  	// Create is emitted when a new route has been created
    19  	Create EventType = iota
    20  	// Delete is emitted when an existing route has been deleted
    21  	Delete
    22  	// Update is emitted when an existing route has been updated
    23  	Update
    24  )
    25  
    26  // String returns human readable event type
    27  func (t EventType) String() string {
    28  	switch t {
    29  	case Create:
    30  		return "create"
    31  	case Delete:
    32  		return "delete"
    33  	case Update:
    34  		return "update"
    35  	default:
    36  		return "unknown"
    37  	}
    38  }
    39  
    40  // Event is returned by a call to Next on the watcher.
    41  type Event struct {
    42  	// Type defines type of event
    43  	Type EventType
    44  	// Timestamp is event timestamp
    45  	Timestamp time.Time
    46  	// Route is table route
    47  	Route Route
    48  }
    49  
    50  // Watcher defines routing table watcher interface
    51  // Watcher returns updates to the routing table
    52  type Watcher interface {
    53  	// Next is a blocking call that returns watch result
    54  	Next() (*Event, error)
    55  	// Chan returns event channel
    56  	Chan() (<-chan *Event, error)
    57  	// Stop stops watcher
    58  	Stop()
    59  }
    60  
    61  // WatchOption is used to define what routes to watch in the table
    62  type WatchOption func(*WatchOptions)
    63  
    64  // WatchOptions are table watcher options
    65  // TODO: expand the options to watch based on other criteria
    66  type WatchOptions struct {
    67  	// Service allows to watch specific service routes
    68  	Service string
    69  }
    70  
    71  // WatchService sets what service routes to watch
    72  // Service is the microservice name
    73  func WatchService(s string) WatchOption {
    74  	return func(o *WatchOptions) {
    75  		o.Service = s
    76  	}
    77  }
    78  
    79  // tableWatcher implements routing table Watcher
    80  type tableWatcher struct {
    81  	sync.RWMutex
    82  	id      string
    83  	opts    WatchOptions
    84  	resChan chan *Event
    85  	done    chan struct{}
    86  }
    87  
    88  // Next returns the next noticed action taken on table
    89  // TODO: right now we only allow to watch particular service
    90  func (w *tableWatcher) Next() (*Event, error) {
    91  	for {
    92  		select {
    93  		case res := <-w.resChan:
    94  			switch w.opts.Service {
    95  			case res.Route.Service, "*":
    96  				return res, nil
    97  			default:
    98  				continue
    99  			}
   100  		case <-w.done:
   101  			return nil, ErrWatcherStopped
   102  		}
   103  	}
   104  }
   105  
   106  // Chan returns watcher events channel
   107  func (w *tableWatcher) Chan() (<-chan *Event, error) {
   108  	return w.resChan, nil
   109  }
   110  
   111  // Stop stops routing table watcher
   112  func (w *tableWatcher) Stop() {
   113  	w.Lock()
   114  	defer w.Unlock()
   115  
   116  	select {
   117  	case <-w.done:
   118  		return
   119  	default:
   120  		close(w.done)
   121  	}
   122  }