package router import ( "errors" ) var ( // ErrWatcherStopped is returned when routing table watcher has been stopped ErrWatcherStopped = errors.New("routing table watcher stopped") ) // WatchOption is used to define what routes to watch in the table type WatchOption func(*WatchOptions) // Watcher defines routing table watcher interface // Watcher returns updates to the routing table type Watcher interface { // Next is a blocking call that returns watch result Next() (*Result, error) // Stop stops watcher Stop() } // Result is returned by a call to Next on the watcher. type Result struct { // Action is routing table action which is either of add, remove or update Action string // Route is table rout Route Route } // Watcher options type WatchOptions struct { // Specify destination address to watch DestAddr string // Specify network to watch Network string } // WatchDestAddr sets what destination to watch // Destination is usually microservice name func WatchDestAddr(a string) WatchOption { return func(o *WatchOptions) { o.DestAddr = a } } // WatchNetwork sets what network to watch func WatchNetwork(n string) WatchOption { return func(o *WatchOptions) { o.Network = n } } type tableWatcher struct { opts WatchOptions resChan chan *Result done chan struct{} } // TODO: this needs to be thought through properly // Next returns the next noticed action taken on table func (w *tableWatcher) Next() (*Result, error) { for { select { case res := <-w.resChan: switch w.opts.DestAddr { case "*", "": if w.opts.Network == "*" || w.opts.Network == res.Route.Options().Network { return res, nil } case res.Route.Options().DestAddr: if w.opts.Network == "*" || w.opts.Network == res.Route.Options().Network { return res, nil } } // ignore if no match is found continue case <-w.done: return nil, ErrWatcherStopped } } } // Stop stops routing table watcher func (w *tableWatcher) Stop() { select { case <-w.done: return default: close(w.done) } }