Update router querying method (#834)
* Add address to router query options. Drop Query interface for QueryOptions * Cleanup isMatch function * Update network proto
This commit is contained in:
@@ -722,8 +722,8 @@ func (r *router) Solicit() error {
|
||||
}
|
||||
|
||||
// Lookup routes in the routing table
|
||||
func (r *router) Lookup(q Query) ([]Route, error) {
|
||||
return r.table.Query(q)
|
||||
func (r *router) Lookup(q ...QueryOption) ([]Route, error) {
|
||||
return r.table.Query(q...)
|
||||
}
|
||||
|
||||
// Watch routes
|
||||
|
||||
@@ -17,11 +17,7 @@ type Router struct {
|
||||
|
||||
// Lookup looks up routes in the routing table and returns them
|
||||
func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.LookupResponse) error {
|
||||
query := router.NewQuery(
|
||||
router.QueryService(req.Query.Service),
|
||||
)
|
||||
|
||||
routes, err := r.Router.Lookup(query)
|
||||
routes, err := r.Router.Lookup(router.QueryService(req.Query.Service))
|
||||
if err != nil {
|
||||
return errors.InternalServerError("go.micro.router", "failed to lookup routes: %v", err)
|
||||
}
|
||||
|
||||
@@ -90,11 +90,7 @@ func (t *Table) List(ctx context.Context, req *pb.Request, resp *pb.ListResponse
|
||||
}
|
||||
|
||||
func (t *Table) Query(ctx context.Context, req *pb.QueryRequest, resp *pb.QueryResponse) error {
|
||||
query := router.NewQuery(
|
||||
router.QueryService(req.Query.Service),
|
||||
)
|
||||
|
||||
routes, err := t.Router.Table().Query(query)
|
||||
routes, err := t.Router.Table().Query(router.QueryService(req.Query.Service))
|
||||
if err != nil {
|
||||
return errors.InternalServerError("go.micro.router", "failed to lookup routes: %s", err)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ type QueryOption func(*QueryOptions)
|
||||
type QueryOptions struct {
|
||||
// Service is destination service name
|
||||
Service string
|
||||
// Address of the service
|
||||
Address string
|
||||
// Gateway is route gateway
|
||||
Gateway string
|
||||
// Network is network address
|
||||
@@ -22,6 +24,13 @@ func QueryService(s string) QueryOption {
|
||||
}
|
||||
}
|
||||
|
||||
// QueryAddress sets service to query
|
||||
func QueryAddress(a string) QueryOption {
|
||||
return func(o *QueryOptions) {
|
||||
o.Address = a
|
||||
}
|
||||
}
|
||||
|
||||
// QueryGateway sets gateway address to query
|
||||
func QueryGateway(g string) QueryOption {
|
||||
return func(o *QueryOptions) {
|
||||
@@ -43,22 +52,12 @@ func QueryRouter(r string) QueryOption {
|
||||
}
|
||||
}
|
||||
|
||||
// Query is routing table query
|
||||
type Query interface {
|
||||
// Options returns query options
|
||||
Options() QueryOptions
|
||||
}
|
||||
|
||||
// query is a basic implementation of Query
|
||||
type query struct {
|
||||
opts QueryOptions
|
||||
}
|
||||
|
||||
// NewQuery creates new query and returns it
|
||||
func NewQuery(opts ...QueryOption) Query {
|
||||
func NewQuery(opts ...QueryOption) QueryOptions {
|
||||
// default options
|
||||
qopts := QueryOptions{
|
||||
Service: "*",
|
||||
Address: "*",
|
||||
Gateway: "*",
|
||||
Network: "*",
|
||||
Router: "*",
|
||||
@@ -68,12 +67,5 @@ func NewQuery(opts ...QueryOption) Query {
|
||||
o(&qopts)
|
||||
}
|
||||
|
||||
return &query{
|
||||
opts: qopts,
|
||||
}
|
||||
}
|
||||
|
||||
// Options returns query options
|
||||
func (q *query) Options() QueryOptions {
|
||||
return q.opts
|
||||
return qopts
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ type Router interface {
|
||||
// Solicit advertises the whole routing table to the network
|
||||
Solicit() error
|
||||
// Lookup queries routes in the routing table
|
||||
Lookup(Query) ([]Route, error)
|
||||
Lookup(...QueryOption) ([]Route, error)
|
||||
// Watch returns a watcher which tracks updates to the routing table
|
||||
Watch(opts ...WatchOption) (Watcher, error)
|
||||
// Start starts the router
|
||||
@@ -55,7 +55,7 @@ type Table interface {
|
||||
// List all routes in the table
|
||||
List() ([]Route, error)
|
||||
// Query routes in the routing table
|
||||
Query(Query) ([]Route, error)
|
||||
Query(...QueryOption) ([]Route, error)
|
||||
}
|
||||
|
||||
// Option used by the router
|
||||
|
||||
@@ -321,13 +321,15 @@ func (s *svc) Stop() error {
|
||||
}
|
||||
|
||||
// Lookup looks up routes in the routing table and returns them
|
||||
func (s *svc) Lookup(q router.Query) ([]router.Route, error) {
|
||||
func (s *svc) Lookup(q ...router.QueryOption) ([]router.Route, error) {
|
||||
// call the router
|
||||
query := router.NewQuery(q...)
|
||||
|
||||
resp, err := s.router.Lookup(context.Background(), &pb.LookupRequest{
|
||||
Query: &pb.Query{
|
||||
Service: q.Options().Service,
|
||||
Gateway: q.Options().Gateway,
|
||||
Network: q.Options().Network,
|
||||
Service: query.Service,
|
||||
Gateway: query.Gateway,
|
||||
Network: query.Network,
|
||||
},
|
||||
}, s.callOpts...)
|
||||
|
||||
|
||||
@@ -90,13 +90,15 @@ func (t *table) List() ([]router.Route, error) {
|
||||
}
|
||||
|
||||
// Lookup looks up routes in the routing table and returns them
|
||||
func (t *table) Query(q router.Query) ([]router.Route, error) {
|
||||
func (t *table) Query(q ...router.QueryOption) ([]router.Route, error) {
|
||||
query := router.NewQuery(q...)
|
||||
|
||||
// call the router
|
||||
resp, err := t.table.Query(context.Background(), &pb.QueryRequest{
|
||||
Query: &pb.Query{
|
||||
Service: q.Options().Service,
|
||||
Gateway: q.Options().Gateway,
|
||||
Network: q.Options().Network,
|
||||
Service: query.Service,
|
||||
Gateway: query.Gateway,
|
||||
Network: query.Network,
|
||||
},
|
||||
}, t.callOpts...)
|
||||
|
||||
|
||||
@@ -135,22 +135,44 @@ func (t *table) List() ([]Route, error) {
|
||||
}
|
||||
|
||||
// isMatch checks if the route matches given query options
|
||||
func isMatch(route Route, gateway, network, router string) bool {
|
||||
if gateway == "*" || gateway == route.Gateway {
|
||||
if network == "*" || network == route.Network {
|
||||
if router == "*" || router == route.Router {
|
||||
return true
|
||||
}
|
||||
func isMatch(route Route, address, gateway, network, router string) bool {
|
||||
// matches the values provided
|
||||
match := func(a, b string) bool {
|
||||
if a == "*" || a == b {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// a simple struct to hold our values
|
||||
type compare struct {
|
||||
a string
|
||||
b string
|
||||
}
|
||||
|
||||
// compare the following values
|
||||
values := []compare{
|
||||
{gateway, route.Gateway},
|
||||
{network, route.Network},
|
||||
{router, route.Router},
|
||||
{address, route.Address},
|
||||
}
|
||||
|
||||
for _, v := range values {
|
||||
// attempt to match each value
|
||||
if !match(v.a, v.b) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// findRoutes finds all the routes for given network and router and returns them
|
||||
func findRoutes(routes map[uint64]Route, gateway, network, router string) []Route {
|
||||
func findRoutes(routes map[uint64]Route, address, gateway, network, router string) []Route {
|
||||
var results []Route
|
||||
for _, route := range routes {
|
||||
if isMatch(route, gateway, network, router) {
|
||||
if isMatch(route, address, gateway, network, router) {
|
||||
results = append(results, route)
|
||||
}
|
||||
}
|
||||
@@ -158,21 +180,24 @@ func findRoutes(routes map[uint64]Route, gateway, network, router string) []Rout
|
||||
}
|
||||
|
||||
// Lookup queries routing table and returns all routes that match the lookup query
|
||||
func (t *table) Query(q Query) ([]Route, error) {
|
||||
func (t *table) Query(q ...QueryOption) ([]Route, error) {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
|
||||
if q.Options().Service != "*" {
|
||||
if _, ok := t.routes[q.Options().Service]; !ok {
|
||||
// create new query options
|
||||
opts := NewQuery(q...)
|
||||
|
||||
if opts.Service != "*" {
|
||||
if _, ok := t.routes[opts.Service]; !ok {
|
||||
return nil, ErrRouteNotFound
|
||||
}
|
||||
return findRoutes(t.routes[q.Options().Service], q.Options().Gateway, q.Options().Network, q.Options().Router), nil
|
||||
return findRoutes(t.routes[opts.Service], opts.Address, opts.Gateway, opts.Network, opts.Router), nil
|
||||
}
|
||||
|
||||
var results []Route
|
||||
// search through all destinations
|
||||
for _, routes := range t.routes {
|
||||
results = append(results, findRoutes(routes, q.Options().Gateway, q.Options().Network, q.Options().Router)...)
|
||||
results = append(results, findRoutes(routes, opts.Address, opts.Gateway, opts.Network, opts.Router)...)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
|
||||
@@ -123,18 +123,15 @@ func TestQuery(t *testing.T) {
|
||||
}
|
||||
|
||||
// return all routes
|
||||
query := NewQuery()
|
||||
|
||||
routes, err := table.Query(query)
|
||||
routes, err := table.Query()
|
||||
if err != nil {
|
||||
t.Errorf("error looking up routes: %s", err)
|
||||
}
|
||||
|
||||
// query routes particular network
|
||||
network := "net1"
|
||||
query = NewQuery(QueryNetwork(network))
|
||||
|
||||
routes, err = table.Query(query)
|
||||
routes, err = table.Query(QueryNetwork(network))
|
||||
if err != nil {
|
||||
t.Errorf("error looking up routes: %s", err)
|
||||
}
|
||||
@@ -151,9 +148,8 @@ func TestQuery(t *testing.T) {
|
||||
|
||||
// query routes for particular gateway
|
||||
gateway := "gw1"
|
||||
query = NewQuery(QueryGateway(gateway))
|
||||
|
||||
routes, err = table.Query(query)
|
||||
routes, err = table.Query(QueryGateway(gateway))
|
||||
if err != nil {
|
||||
t.Errorf("error looking up routes: %s", err)
|
||||
}
|
||||
@@ -168,9 +164,8 @@ func TestQuery(t *testing.T) {
|
||||
|
||||
// query routes for particular router
|
||||
router := "rtr1"
|
||||
query = NewQuery(QueryRouter(router))
|
||||
|
||||
routes, err = table.Query(query)
|
||||
routes, err = table.Query(QueryRouter(router))
|
||||
if err != nil {
|
||||
t.Errorf("error looking up routes: %s", err)
|
||||
}
|
||||
@@ -184,13 +179,13 @@ func TestQuery(t *testing.T) {
|
||||
}
|
||||
|
||||
// query particular gateway and network
|
||||
query = NewQuery(
|
||||
query := []QueryOption{
|
||||
QueryGateway(gateway),
|
||||
QueryNetwork(network),
|
||||
QueryRouter(router),
|
||||
)
|
||||
}
|
||||
|
||||
routes, err = table.Query(query)
|
||||
routes, err = table.Query(query...)
|
||||
if err != nil {
|
||||
t.Errorf("error looking up routes: %s", err)
|
||||
}
|
||||
@@ -212,9 +207,7 @@ func TestQuery(t *testing.T) {
|
||||
}
|
||||
|
||||
// non-existen route query
|
||||
query = NewQuery(QueryService("foobar"))
|
||||
|
||||
routes, err = table.Query(query)
|
||||
routes, err = table.Query(QueryService("foobar"))
|
||||
if err != ErrRouteNotFound {
|
||||
t.Errorf("error looking up routes. Expected: %s, found: %s", ErrRouteNotFound, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user