github.com/annwntech/go-micro/v2@v2.9.5/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  	// Unique id of the event
    43  	Id string
    44  	// Type defines type of event
    45  	Type EventType
    46  	// Timestamp is event timestamp
    47  	Timestamp time.Time
    48  	// Route is table route
    49  	Route Route
    50  }
    51  
    52  // Watcher defines routing table watcher interface
    53  // Watcher returns updates to the routing table
    54  type Watcher interface {
    55  	// Next is a blocking call that returns watch result
    56  	Next() (*Event, error)
    57  	// Chan returns event channel
    58  	Chan() (<-chan *Event, error)
    59  	// Stop stops watcher
    60  	Stop()
    61  }
    62  
    63  // WatchOption is used to define what routes to watch in the table
    64  type WatchOption func(*WatchOptions)
    65  
    66  // WatchOptions are table watcher options
    67  // TODO: expand the options to watch based on other criteria
    68  type WatchOptions struct {
    69  	// Service allows to watch specific service routes
    70  	Service string
    71  }
    72  
    73  // WatchService sets what service routes to watch
    74  // Service is the microservice name
    75  func WatchService(s string) WatchOption {
    76  	return func(o *WatchOptions) {
    77  		o.Service = s
    78  	}
    79  }
    80  
    81  // tableWatcher implements routing table Watcher
    82  type tableWatcher struct {
    83  	sync.RWMutex
    84  	id      string
    85  	opts    WatchOptions
    86  	resChan chan *Event
    87  	done    chan struct{}
    88  }
    89  
    90  // Next returns the next noticed action taken on table
    91  // TODO: right now we only allow to watch particular service
    92  func (w *tableWatcher) Next() (*Event, error) {
    93  	for {
    94  		select {
    95  		case res := <-w.resChan:
    96  			switch w.opts.Service {
    97  			case res.Route.Service, "*":
    98  				return res, nil
    99  			default:
   100  				continue
   101  			}
   102  		case <-w.done:
   103  			return nil, ErrWatcherStopped
   104  		}
   105  	}
   106  }
   107  
   108  // Chan returns watcher events channel
   109  func (w *tableWatcher) Chan() (<-chan *Event, error) {
   110  	return w.resChan, nil
   111  }
   112  
   113  // Stop stops routing table watcher
   114  func (w *tableWatcher) Stop() {
   115  	w.Lock()
   116  	defer w.Unlock()
   117  
   118  	select {
   119  	case <-w.done:
   120  		return
   121  	default:
   122  		close(w.done)
   123  	}
   124  }