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:
Asim Aslam
2019-10-09 17:13:52 +01:00
committed by GitHub
parent 107b7419b7
commit fe94237448
15 changed files with 249 additions and 122 deletions

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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...)

View File

@@ -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...)

View File

@@ -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

View File

@@ -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)
}