gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/network/service/handler/handler.go (about)

     1  // Package handler implements network RPC handler
     2  package handler
     3  
     4  import (
     5  	"context"
     6  
     7  	"gitee.com/liuxuezhan/go-micro-v1.18.0/errors"
     8  	"gitee.com/liuxuezhan/go-micro-v1.18.0/network"
     9  	pbNet "gitee.com/liuxuezhan/go-micro-v1.18.0/network/proto"
    10  	"gitee.com/liuxuezhan/go-micro-v1.18.0/router"
    11  	pbRtr "gitee.com/liuxuezhan/go-micro-v1.18.0/router/proto"
    12  	"gitee.com/liuxuezhan/go-micro-v1.18.0/util/log"
    13  )
    14  
    15  // Network implements network handler
    16  type Network struct {
    17  	Network network.Network
    18  }
    19  
    20  func flatten(n network.Node, visited map[string]bool) []network.Node {
    21  	// if node is nil runaway
    22  	if n == nil {
    23  		return nil
    24  	}
    25  
    26  	// set visisted
    27  	if visited == nil {
    28  		visited = make(map[string]bool)
    29  	}
    30  
    31  	// create new list of nodes
    32  	//nolint:prealloc
    33  	var nodes []network.Node
    34  
    35  	// check if already visited
    36  	if !visited[n.Id()] {
    37  		// append the current node
    38  		nodes = append(nodes, n)
    39  	}
    40  
    41  	// set to visited
    42  	visited[n.Id()] = true
    43  
    44  	// visit the list of peers
    45  	for _, node := range n.Peers() {
    46  		nodes = append(nodes, flatten(node, visited)...)
    47  	}
    48  
    49  	return nodes
    50  }
    51  
    52  func (n *Network) Connect(ctx context.Context, req *pbNet.ConnectRequest, resp *pbNet.ConnectResponse) error {
    53  	if len(req.Nodes) == 0 {
    54  		return nil
    55  	}
    56  
    57  	// get list of existing nodes
    58  	nodes := n.Network.Options().Nodes
    59  
    60  	// generate a node map
    61  	nodeMap := make(map[string]bool)
    62  
    63  	for _, node := range nodes {
    64  		nodeMap[node] = true
    65  	}
    66  
    67  	for _, node := range req.Nodes {
    68  		// TODO: we may have been provided a network only
    69  		// so process anad resolve node.Network
    70  		if len(node.Address) == 0 {
    71  			continue
    72  		}
    73  
    74  		// already exists
    75  		if _, ok := nodeMap[node.Address]; ok {
    76  			continue
    77  		}
    78  
    79  		nodeMap[node.Address] = true
    80  		nodes = append(nodes, node.Address)
    81  	}
    82  
    83  	log.Infof("Network.Connect setting peers: %v", nodes)
    84  
    85  	// reinitialise the peers
    86  	n.Network.Init(
    87  		network.Nodes(nodes...),
    88  	)
    89  
    90  	// call the connect method
    91  	n.Network.Connect()
    92  
    93  	return nil
    94  }
    95  
    96  // Nodes returns the list of nodes
    97  func (n *Network) Nodes(ctx context.Context, req *pbNet.NodesRequest, resp *pbNet.NodesResponse) error {
    98  	// root node
    99  	nodes := map[string]network.Node{}
   100  
   101  	// get peers encoded into protobuf
   102  	peers := flatten(n.Network, nil)
   103  
   104  	// walk all the peers
   105  	for _, peer := range peers {
   106  		if peer == nil {
   107  			continue
   108  		}
   109  		if _, ok := nodes[peer.Id()]; ok {
   110  			continue
   111  		}
   112  
   113  		// add to visited list
   114  		nodes[n.Network.Id()] = peer
   115  
   116  		resp.Nodes = append(resp.Nodes, &pbNet.Node{
   117  			Id:      peer.Id(),
   118  			Address: peer.Address(),
   119  		})
   120  	}
   121  
   122  	return nil
   123  }
   124  
   125  // Graph returns the network graph from this root node
   126  func (n *Network) Graph(ctx context.Context, req *pbNet.GraphRequest, resp *pbNet.GraphResponse) error {
   127  	depth := uint(req.Depth)
   128  	if depth <= 0 || depth > network.MaxDepth {
   129  		depth = network.MaxDepth
   130  	}
   131  
   132  	// get peers encoded into protobuf
   133  	peers := network.PeersToProto(n.Network, depth)
   134  
   135  	// set the root node
   136  	resp.Root = peers
   137  
   138  	return nil
   139  }
   140  
   141  // Routes returns a list of routing table routes
   142  func (n *Network) Routes(ctx context.Context, req *pbNet.RoutesRequest, resp *pbNet.RoutesResponse) error {
   143  	// build query
   144  
   145  	var qOpts []router.QueryOption
   146  
   147  	if q := req.Query; q != nil {
   148  		if len(q.Service) > 0 {
   149  			qOpts = append(qOpts, router.QueryService(q.Service))
   150  		}
   151  		if len(q.Address) > 0 {
   152  			qOpts = append(qOpts, router.QueryAddress(q.Address))
   153  		}
   154  		if len(q.Gateway) > 0 {
   155  			qOpts = append(qOpts, router.QueryGateway(q.Gateway))
   156  		}
   157  		if len(q.Router) > 0 {
   158  			qOpts = append(qOpts, router.QueryRouter(q.Router))
   159  		}
   160  		if len(q.Network) > 0 {
   161  			qOpts = append(qOpts, router.QueryNetwork(q.Network))
   162  		}
   163  	}
   164  
   165  	routes, err := n.Network.Options().Router.Table().Query(qOpts...)
   166  	if err != nil {
   167  		return errors.InternalServerError("go.micro.network", "failed to list routes: %s", err)
   168  	}
   169  
   170  	respRoutes := make([]*pbRtr.Route, 0, len(routes))
   171  	for _, route := range routes {
   172  		respRoute := &pbRtr.Route{
   173  			Service: route.Service,
   174  			Address: route.Address,
   175  			Gateway: route.Gateway,
   176  			Network: route.Network,
   177  			Router:  route.Router,
   178  			Link:    route.Link,
   179  			Metric:  int64(route.Metric),
   180  		}
   181  		respRoutes = append(respRoutes, respRoute)
   182  	}
   183  
   184  	resp.Routes = respRoutes
   185  
   186  	return nil
   187  }
   188  
   189  // Services returns a list of services based on the routing table
   190  func (n *Network) Services(ctx context.Context, req *pbNet.ServicesRequest, resp *pbNet.ServicesResponse) error {
   191  	routes, err := n.Network.Options().Router.Table().List()
   192  	if err != nil {
   193  		return errors.InternalServerError("go.micro.network", "failed to list services: %s", err)
   194  	}
   195  
   196  	services := make(map[string]bool)
   197  
   198  	for _, route := range routes {
   199  		if _, ok := services[route.Service]; ok {
   200  			continue
   201  		}
   202  		services[route.Service] = true
   203  		resp.Services = append(resp.Services, route.Service)
   204  	}
   205  
   206  	return nil
   207  }