diff --git a/router/default.go b/router/default.go index 273eeda6..b7845b8e 100644 --- a/router/default.go +++ b/router/default.go @@ -682,18 +682,59 @@ func (r *router) flushRouteEvents(evType EventType) ([]*Event, error) { return nil, fmt.Errorf("failed listing routes: %s", err) } - // TODO: flush the routes based on strategy here - // - collapse the routes per service-metric-locality (prefer your routes) + r.RLock() + advertStrategy := r.options.Advertise + r.RUnlock() + + if advertStrategy == All { + // build a list of events to advertise + events := make([]*Event, len(routes)) + for i, route := range routes { + event := &Event{ + Type: evType, + Timestamp: time.Now(), + Route: route, + } + events[i] = event + } + return events, nil + } + + // routeMap stores optimal routes per service + optimalRoutes := make(map[string]Route) + + // go through all routes found in the routing table and collapse them to optimal routes + for _, route := range routes { + optimal, ok := optimalRoutes[route.Service] + if !ok { + optimalRoutes[route.Service] = route + continue + } + // if the current optimal route metric is higher than routing table route, replace it + if optimal.Metric > route.Metric { + optimalRoutes[route.Service] = route + continue + } + // if the metrics are the same, prefer advertising your own route + if optimal.Metric == route.Metric { + if route.Router == r.options.Id { + optimalRoutes[route.Service] = route + continue + } + } + } // build a list of events to advertise - events := make([]*Event, len(routes)) - for i, route := range routes { + events := make([]*Event, len(optimalRoutes)) + i := 0 + for _, route := range optimalRoutes { event := &Event{ Type: evType, Timestamp: time.Now(), Route: route, } events[i] = event + i++ } return events, nil diff --git a/router/options.go b/router/options.go index 47fd82e8..37cfe5aa 100644 --- a/router/options.go +++ b/router/options.go @@ -76,9 +76,10 @@ func Advertise(a Strategy) Option { // DefaultOptions returns router default options func DefaultOptions() Options { return Options{ - Id: uuid.New().String(), - Address: DefaultAddress, - Network: DefaultNetwork, - Registry: registry.DefaultRegistry, + Id: uuid.New().String(), + Address: DefaultAddress, + Network: DefaultNetwork, + Registry: registry.DefaultRegistry, + Advertise: Optimal, } } diff --git a/router/router.go b/router/router.go index 938eaf5d..d0d32c0e 100644 --- a/router/router.go +++ b/router/router.go @@ -149,6 +149,18 @@ const ( Optimal ) +// String returns human readable Strategy +func (s Strategy) String() string { + switch s { + case All: + return "all" + case Optimal: + return "optimal" + default: + return "unknown" + } +} + // NewRouter creates new Router and returns it func NewRouter(opts ...Option) Router { return newRouter(opts...)