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

     1  package handler
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"time"
     7  
     8  	"gitee.com/liuxuezhan/go-micro-v1.18.0/errors"
     9  	"gitee.com/liuxuezhan/go-micro-v1.18.0/router"
    10  	pb "gitee.com/liuxuezhan/go-micro-v1.18.0/router/proto"
    11  )
    12  
    13  // Router implements router handler
    14  type Router struct {
    15  	Router router.Router
    16  }
    17  
    18  // Lookup looks up routes in the routing table and returns them
    19  func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.LookupResponse) error {
    20  	routes, err := r.Router.Lookup(router.QueryService(req.Query.Service))
    21  	if err != nil {
    22  		return errors.InternalServerError("go.micro.router", "failed to lookup routes: %v", err)
    23  	}
    24  
    25  	respRoutes := make([]*pb.Route, 0, len(routes))
    26  	for _, route := range routes {
    27  		respRoute := &pb.Route{
    28  			Service: route.Service,
    29  			Address: route.Address,
    30  			Gateway: route.Gateway,
    31  			Network: route.Network,
    32  			Router:  route.Router,
    33  			Link:    route.Link,
    34  			Metric:  route.Metric,
    35  		}
    36  		respRoutes = append(respRoutes, respRoute)
    37  	}
    38  
    39  	resp.Routes = respRoutes
    40  
    41  	return nil
    42  }
    43  
    44  // Solicit triggers full routing table advertisement
    45  func (r *Router) Solicit(ctx context.Context, req *pb.Request, resp *pb.Response) error {
    46  	if err := r.Router.Solicit(); err != nil {
    47  		return err
    48  	}
    49  
    50  	return nil
    51  }
    52  
    53  // Advertise streams router advertisements
    54  func (r *Router) Advertise(ctx context.Context, req *pb.Request, stream pb.Router_AdvertiseStream) error {
    55  	advertChan, err := r.Router.Advertise()
    56  	if err != nil {
    57  		return errors.InternalServerError("go.micro.router", "failed to get adverts: %v", err)
    58  	}
    59  
    60  	for advert := range advertChan {
    61  		var events []*pb.Event
    62  		for _, event := range advert.Events {
    63  			route := &pb.Route{
    64  				Service: event.Route.Service,
    65  				Address: event.Route.Address,
    66  				Gateway: event.Route.Gateway,
    67  				Network: event.Route.Network,
    68  				Router:  event.Route.Router,
    69  				Link:    event.Route.Link,
    70  				Metric:  event.Route.Metric,
    71  			}
    72  			e := &pb.Event{
    73  				Type:      pb.EventType(event.Type),
    74  				Timestamp: event.Timestamp.UnixNano(),
    75  				Route:     route,
    76  			}
    77  			events = append(events, e)
    78  		}
    79  
    80  		advert := &pb.Advert{
    81  			Id:        advert.Id,
    82  			Type:      pb.AdvertType(advert.Type),
    83  			Timestamp: advert.Timestamp.UnixNano(),
    84  			Events:    events,
    85  		}
    86  
    87  		// send the advert
    88  		err := stream.Send(advert)
    89  		if err == io.EOF {
    90  			return nil
    91  		}
    92  		if err != nil {
    93  			return errors.InternalServerError("go.micro.router", "error sending message %v", err)
    94  		}
    95  	}
    96  
    97  	return nil
    98  }
    99  
   100  // Process processes advertisements
   101  func (r *Router) Process(ctx context.Context, req *pb.Advert, rsp *pb.ProcessResponse) error {
   102  	events := make([]*router.Event, len(req.Events))
   103  	for i, event := range req.Events {
   104  		route := router.Route{
   105  			Service: event.Route.Service,
   106  			Address: event.Route.Address,
   107  			Gateway: event.Route.Gateway,
   108  			Network: event.Route.Network,
   109  			Router:  event.Route.Router,
   110  			Link:    event.Route.Link,
   111  			Metric:  event.Route.Metric,
   112  		}
   113  
   114  		events[i] = &router.Event{
   115  			Type:      router.EventType(event.Type),
   116  			Timestamp: time.Unix(0, event.Timestamp),
   117  			Route:     route,
   118  		}
   119  	}
   120  
   121  	advert := &router.Advert{
   122  		Id:        req.Id,
   123  		Type:      router.AdvertType(req.Type),
   124  		Timestamp: time.Unix(0, req.Timestamp),
   125  		TTL:       time.Duration(req.Ttl),
   126  		Events:    events,
   127  	}
   128  
   129  	if err := r.Router.Process(advert); err != nil {
   130  		return errors.InternalServerError("go.micro.router", "error publishing advert: %v", err)
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  // Status returns router status
   137  func (r *Router) Status(ctx context.Context, req *pb.Request, rsp *pb.StatusResponse) error {
   138  	status := r.Router.Status()
   139  
   140  	rsp.Status = &pb.Status{
   141  		Code: status.Code.String(),
   142  	}
   143  
   144  	if status.Error != nil {
   145  		rsp.Status.Error = status.Error.Error()
   146  	}
   147  
   148  	return nil
   149  }
   150  
   151  // Watch streans routing table events
   152  func (r *Router) Watch(ctx context.Context, req *pb.WatchRequest, stream pb.Router_WatchStream) error {
   153  	watcher, err := r.Router.Watch()
   154  	if err != nil {
   155  		return errors.InternalServerError("go.micro.router", "failed creating event watcher: %v", err)
   156  	}
   157  
   158  	defer stream.Close()
   159  
   160  	for {
   161  		event, err := watcher.Next()
   162  		if err == router.ErrWatcherStopped {
   163  			return errors.InternalServerError("go.micro.router", "watcher stopped")
   164  		}
   165  
   166  		if err != nil {
   167  			return errors.InternalServerError("go.micro.router", "error watching events: %v", err)
   168  		}
   169  
   170  		route := &pb.Route{
   171  			Service: event.Route.Service,
   172  			Address: event.Route.Address,
   173  			Gateway: event.Route.Gateway,
   174  			Network: event.Route.Network,
   175  			Router:  event.Route.Router,
   176  			Link:    event.Route.Link,
   177  			Metric:  event.Route.Metric,
   178  		}
   179  
   180  		tableEvent := &pb.Event{
   181  			Type:      pb.EventType(event.Type),
   182  			Timestamp: event.Timestamp.UnixNano(),
   183  			Route:     route,
   184  		}
   185  
   186  		if err := stream.Send(tableEvent); err != nil {
   187  			return err
   188  		}
   189  	}
   190  }