github.com/annwntech/go-micro/v2@v2.9.5/router/service/service.go (about) 1 package service 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "sync" 8 "time" 9 10 "github.com/annwntech/go-micro/v2/client" 11 "github.com/annwntech/go-micro/v2/router" 12 pb "github.com/annwntech/go-micro/v2/router/service/proto" 13 ) 14 15 type svc struct { 16 sync.RWMutex 17 opts router.Options 18 callOpts []client.CallOption 19 router pb.RouterService 20 table *table 21 exit chan bool 22 errChan chan error 23 advertChan chan *router.Advert 24 } 25 26 // NewRouter creates new service router and returns it 27 func NewRouter(opts ...router.Option) router.Router { 28 // get default options 29 options := router.DefaultOptions() 30 31 // apply requested options 32 for _, o := range opts { 33 o(&options) 34 } 35 36 // NOTE: might need some client opts here 37 cli := client.DefaultClient 38 39 // set options client 40 if options.Client != nil { 41 cli = options.Client 42 } 43 44 // NOTE: should we have Client/Service option in router.Options? 45 s := &svc{ 46 opts: options, 47 router: pb.NewRouterService(router.DefaultName, cli), 48 } 49 50 // set the router address to call 51 if len(options.Address) > 0 { 52 s.callOpts = []client.CallOption{ 53 client.WithAddress(options.Address), 54 } 55 } 56 // set the table 57 s.table = &table{pb.NewTableService(router.DefaultName, cli), s.callOpts} 58 59 return s 60 } 61 62 // Init initializes router with given options 63 func (s *svc) Init(opts ...router.Option) error { 64 s.Lock() 65 defer s.Unlock() 66 67 for _, o := range opts { 68 o(&s.opts) 69 } 70 71 return nil 72 } 73 74 // Options returns router options 75 func (s *svc) Options() router.Options { 76 s.Lock() 77 opts := s.opts 78 s.Unlock() 79 80 return opts 81 } 82 83 // Table returns routing table 84 func (s *svc) Table() router.Table { 85 return s.table 86 } 87 88 // Start starts the service 89 func (s *svc) Start() error { 90 s.Lock() 91 defer s.Unlock() 92 return nil 93 } 94 95 func (s *svc) advertiseEvents(advertChan chan *router.Advert, stream pb.Router_AdvertiseService) error { 96 go func() { 97 <-s.exit 98 stream.Close() 99 }() 100 101 var advErr error 102 103 for { 104 resp, err := stream.Recv() 105 if err != nil { 106 if err != io.EOF { 107 advErr = err 108 } 109 break 110 } 111 112 events := make([]*router.Event, len(resp.Events)) 113 for i, event := range resp.Events { 114 route := router.Route{ 115 Service: event.Route.Service, 116 Address: event.Route.Address, 117 Gateway: event.Route.Gateway, 118 Network: event.Route.Network, 119 Link: event.Route.Link, 120 Metric: event.Route.Metric, 121 } 122 123 events[i] = &router.Event{ 124 Id: event.Id, 125 Type: router.EventType(event.Type), 126 Timestamp: time.Unix(0, event.Timestamp), 127 Route: route, 128 } 129 } 130 131 advert := &router.Advert{ 132 Id: resp.Id, 133 Type: router.AdvertType(resp.Type), 134 Timestamp: time.Unix(0, resp.Timestamp), 135 TTL: time.Duration(resp.Ttl), 136 Events: events, 137 } 138 139 select { 140 case advertChan <- advert: 141 case <-s.exit: 142 close(advertChan) 143 return nil 144 } 145 } 146 147 // close the channel on exit 148 close(advertChan) 149 150 return advErr 151 } 152 153 // Advertise advertises routes to the network 154 func (s *svc) Advertise() (<-chan *router.Advert, error) { 155 s.Lock() 156 defer s.Unlock() 157 158 stream, err := s.router.Advertise(context.Background(), &pb.Request{}, s.callOpts...) 159 if err != nil { 160 return nil, fmt.Errorf("failed getting advert stream: %s", err) 161 } 162 163 // create advertise and event channels 164 advertChan := make(chan *router.Advert) 165 go s.advertiseEvents(advertChan, stream) 166 167 return advertChan, nil 168 } 169 170 // Process processes incoming adverts 171 func (s *svc) Process(advert *router.Advert) error { 172 events := make([]*pb.Event, 0, len(advert.Events)) 173 for _, event := range advert.Events { 174 route := &pb.Route{ 175 Service: event.Route.Service, 176 Address: event.Route.Address, 177 Gateway: event.Route.Gateway, 178 Network: event.Route.Network, 179 Link: event.Route.Link, 180 Metric: event.Route.Metric, 181 } 182 e := &pb.Event{ 183 Id: event.Id, 184 Type: pb.EventType(event.Type), 185 Timestamp: event.Timestamp.UnixNano(), 186 Route: route, 187 } 188 events = append(events, e) 189 } 190 191 advertReq := &pb.Advert{ 192 Id: s.Options().Id, 193 Type: pb.AdvertType(advert.Type), 194 Timestamp: advert.Timestamp.UnixNano(), 195 Events: events, 196 } 197 198 if _, err := s.router.Process(context.Background(), advertReq, s.callOpts...); err != nil { 199 return err 200 } 201 202 return nil 203 } 204 205 // Remote router cannot be stopped 206 func (s *svc) Stop() error { 207 s.Lock() 208 defer s.Unlock() 209 210 select { 211 case <-s.exit: 212 return nil 213 default: 214 close(s.exit) 215 } 216 217 return nil 218 } 219 220 // Lookup looks up routes in the routing table and returns them 221 func (s *svc) Lookup(q ...router.QueryOption) ([]router.Route, error) { 222 // call the router 223 query := router.NewQuery(q...) 224 225 resp, err := s.router.Lookup(context.Background(), &pb.LookupRequest{ 226 Query: &pb.Query{ 227 Service: query.Service, 228 Gateway: query.Gateway, 229 Network: query.Network, 230 }, 231 }, s.callOpts...) 232 233 // errored out 234 if err != nil { 235 return nil, err 236 } 237 238 routes := make([]router.Route, len(resp.Routes)) 239 for i, route := range resp.Routes { 240 routes[i] = router.Route{ 241 Service: route.Service, 242 Address: route.Address, 243 Gateway: route.Gateway, 244 Network: route.Network, 245 Link: route.Link, 246 Metric: route.Metric, 247 } 248 } 249 250 return routes, nil 251 } 252 253 // Watch returns a watcher which allows to track updates to the routing table 254 func (s *svc) Watch(opts ...router.WatchOption) (router.Watcher, error) { 255 rsp, err := s.router.Watch(context.Background(), &pb.WatchRequest{}, s.callOpts...) 256 if err != nil { 257 return nil, err 258 } 259 options := router.WatchOptions{ 260 Service: "*", 261 } 262 for _, o := range opts { 263 o(&options) 264 } 265 return newWatcher(rsp, options) 266 } 267 268 // Returns the router implementation 269 func (s *svc) String() string { 270 return "service" 271 }