72ef032162
This commit also adds Route hash function, lots of debug messages for now and String() methods for various API objects.
145 lines
3.0 KiB
Go
145 lines
3.0 KiB
Go
package router
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/micro/go-log"
|
|
"github.com/olekukonko/tablewriter"
|
|
)
|
|
|
|
var (
|
|
// ErrWatcherStopped is returned when routing table watcher has been stopped
|
|
ErrWatcherStopped = errors.New("watcher stopped")
|
|
)
|
|
|
|
// EventType defines routing table event
|
|
type EventType int
|
|
|
|
const (
|
|
// CreateEvent is emitted when a new route has been created
|
|
CreateEvent EventType = iota
|
|
// DeleteEvent is emitted when an existing route has been deleted
|
|
DeleteEvent
|
|
// UpdateEvent is emitted when an existing route has been updated
|
|
UpdateEvent
|
|
)
|
|
|
|
// String returns string representation of the event
|
|
func (et EventType) String() string {
|
|
switch et {
|
|
case CreateEvent:
|
|
return "CREATE"
|
|
case DeleteEvent:
|
|
return "DELETE"
|
|
case UpdateEvent:
|
|
return "UPDATE"
|
|
default:
|
|
return "UNKNOWN"
|
|
}
|
|
}
|
|
|
|
// Event is returned by a call to Next on the watcher.
|
|
type Event struct {
|
|
// Type defines type of event
|
|
Type EventType
|
|
// Timestamp is event timestamp
|
|
Timestamp time.Time
|
|
// Route is table route
|
|
Route Route
|
|
}
|
|
|
|
// String prints human readable Event
|
|
func (e Event) String() string {
|
|
return fmt.Sprintf("[EVENT] Type: %s\nRoute:\n%s", e.Type, e.Route)
|
|
}
|
|
|
|
// 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() (*Event, error)
|
|
// Chan returns event channel
|
|
Chan() (<-chan *Event, error)
|
|
// Stop stops watcher
|
|
Stop()
|
|
}
|
|
|
|
// WatchOptions are table watcher options
|
|
type WatchOptions struct {
|
|
// Specify destination address to watch
|
|
Destination string
|
|
}
|
|
|
|
// WatchDestination sets what destination to watch
|
|
// Destination is usually microservice name
|
|
func WatchDestination(d string) WatchOption {
|
|
return func(o *WatchOptions) {
|
|
o.Destination = d
|
|
}
|
|
}
|
|
|
|
type tableWatcher struct {
|
|
opts WatchOptions
|
|
resChan chan *Event
|
|
done chan struct{}
|
|
}
|
|
|
|
// Next returns the next noticed action taken on table
|
|
// TODO: this needs to be thought through properly;
|
|
// right now we only allow to watch destination
|
|
func (w *tableWatcher) Next() (*Event, error) {
|
|
for {
|
|
select {
|
|
case res := <-w.resChan:
|
|
switch w.opts.Destination {
|
|
case res.Route.Destination, "*":
|
|
return res, nil
|
|
default:
|
|
log.Logf("no table watcher available to receive the event")
|
|
continue
|
|
}
|
|
case <-w.done:
|
|
return nil, ErrWatcherStopped
|
|
}
|
|
}
|
|
}
|
|
|
|
// Chan returns watcher events channel
|
|
func (w *tableWatcher) Chan() (<-chan *Event, error) {
|
|
return w.resChan, nil
|
|
}
|
|
|
|
// Stop stops routing table watcher
|
|
func (w *tableWatcher) Stop() {
|
|
select {
|
|
case <-w.done:
|
|
return
|
|
default:
|
|
close(w.done)
|
|
}
|
|
}
|
|
|
|
// String prints debug information
|
|
func (w *tableWatcher) String() string {
|
|
sb := &strings.Builder{}
|
|
|
|
table := tablewriter.NewWriter(sb)
|
|
table.SetHeader([]string{"Destination"})
|
|
|
|
data := []string{
|
|
w.opts.Destination,
|
|
}
|
|
table.Append(data)
|
|
|
|
// render table into sb
|
|
table.Render()
|
|
|
|
return sb.String()
|
|
}
|