gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/router/service/service.go (about) 1 package service 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "sync" 9 "time" 10 11 "gitee.com/liuxuezhan/go-micro-v1.18.0/client" 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/router" 13 pb "gitee.com/liuxuezhan/go-micro-v1.18.0/router/proto" 14 ) 15 16 type svc struct { 17 sync.RWMutex 18 opts router.Options 19 callOpts []client.CallOption 20 router pb.RouterService 21 table *table 22 status *router.Status 23 exit chan bool 24 errChan chan error 25 advertChan chan *router.Advert 26 } 27 28 // NewRouter creates new service router and returns it 29 func NewRouter(opts ...router.Option) router.Router { 30 // get default options 31 options := router.DefaultOptions() 32 33 // apply requested options 34 for _, o := range opts { 35 o(&options) 36 } 37 38 // NOTE: might need some client opts here 39 cli := client.DefaultClient 40 41 // set options client 42 if options.Client != nil { 43 cli = options.Client 44 } 45 46 // set the status to Stopped 47 status := &router.Status{ 48 Code: router.Stopped, 49 Error: nil, 50 } 51 52 // NOTE: should we have Client/Service option in router.Options? 53 s := &svc{ 54 opts: options, 55 status: status, 56 router: pb.NewRouterService(router.DefaultName, cli), 57 } 58 59 // set the router address to call 60 if len(options.Address) > 0 { 61 s.callOpts = []client.CallOption{ 62 client.WithAddress(options.Address), 63 } 64 } 65 // set the table 66 s.table = &table{pb.NewTableService(router.DefaultName, cli), s.callOpts} 67 68 return s 69 } 70 71 // Init initializes router with given options 72 func (s *svc) Init(opts ...router.Option) error { 73 s.Lock() 74 defer s.Unlock() 75 76 for _, o := range opts { 77 o(&s.opts) 78 } 79 80 return nil 81 } 82 83 // Options returns router options 84 func (s *svc) Options() router.Options { 85 s.Lock() 86 opts := s.opts 87 s.Unlock() 88 89 return opts 90 } 91 92 // Table returns routing table 93 func (s *svc) Table() router.Table { 94 return s.table 95 } 96 97 // Start starts the service 98 func (s *svc) Start() error { 99 s.Lock() 100 defer s.Unlock() 101 102 s.status = &router.Status{ 103 Code: router.Running, 104 Error: nil, 105 } 106 107 return nil 108 } 109 110 func (s *svc) advertiseEvents(advertChan chan *router.Advert, stream pb.Router_AdvertiseService) error { 111 go func() { 112 <-s.exit 113 stream.Close() 114 }() 115 116 var advErr error 117 118 for { 119 resp, err := stream.Recv() 120 if err != nil { 121 if err != io.EOF { 122 advErr = err 123 } 124 break 125 } 126 127 events := make([]*router.Event, len(resp.Events)) 128 for i, event := range resp.Events { 129 route := router.Route{ 130 Service: event.Route.Service, 131 Address: event.Route.Address, 132 Gateway: event.Route.Gateway, 133 Network: event.Route.Network, 134 Link: event.Route.Link, 135 Metric: event.Route.Metric, 136 } 137 138 events[i] = &router.Event{ 139 Type: router.EventType(event.Type), 140 Timestamp: time.Unix(0, event.Timestamp), 141 Route: route, 142 } 143 } 144 145 advert := &router.Advert{ 146 Id: resp.Id, 147 Type: router.AdvertType(resp.Type), 148 Timestamp: time.Unix(0, resp.Timestamp), 149 TTL: time.Duration(resp.Ttl), 150 Events: events, 151 } 152 153 select { 154 case advertChan <- advert: 155 case <-s.exit: 156 close(advertChan) 157 return nil 158 } 159 } 160 161 // close the channel on exit 162 close(advertChan) 163 164 return advErr 165 } 166 167 // Advertise advertises routes to the network 168 func (s *svc) Advertise() (<-chan *router.Advert, error) { 169 s.Lock() 170 defer s.Unlock() 171 172 switch s.status.Code { 173 case router.Running, router.Advertising: 174 stream, err := s.router.Advertise(context.Background(), &pb.Request{}, s.callOpts...) 175 if err != nil { 176 return nil, fmt.Errorf("failed getting advert stream: %s", err) 177 } 178 // create advertise and event channels 179 advertChan := make(chan *router.Advert) 180 go s.advertiseEvents(advertChan, stream) 181 return advertChan, nil 182 case router.Stopped: 183 return nil, fmt.Errorf("not running") 184 } 185 186 return nil, fmt.Errorf("error: %s", s.status.Error) 187 } 188 189 // Process processes incoming adverts 190 func (s *svc) Process(advert *router.Advert) error { 191 events := make([]*pb.Event, 0, len(advert.Events)) 192 for _, event := range advert.Events { 193 route := &pb.Route{ 194 Service: event.Route.Service, 195 Address: event.Route.Address, 196 Gateway: event.Route.Gateway, 197 Network: event.Route.Network, 198 Link: event.Route.Link, 199 Metric: event.Route.Metric, 200 } 201 e := &pb.Event{ 202 Type: pb.EventType(event.Type), 203 Timestamp: event.Timestamp.UnixNano(), 204 Route: route, 205 } 206 events = append(events, e) 207 } 208 209 advertReq := &pb.Advert{ 210 Id: s.Options().Id, 211 Type: pb.AdvertType(advert.Type), 212 Timestamp: advert.Timestamp.UnixNano(), 213 Events: events, 214 } 215 216 if _, err := s.router.Process(context.Background(), advertReq, s.callOpts...); err != nil { 217 return err 218 } 219 220 return nil 221 } 222 223 // Solicit advertise all routes 224 func (s *svc) Solicit() error { 225 // list all the routes 226 routes, err := s.table.List() 227 if err != nil { 228 return err 229 } 230 231 // build events to advertise 232 events := make([]*router.Event, len(routes)) 233 for i := range events { 234 events[i] = &router.Event{ 235 Type: router.Update, 236 Timestamp: time.Now(), 237 Route: routes[i], 238 } 239 } 240 241 advert := &router.Advert{ 242 Id: s.opts.Id, 243 Type: router.RouteUpdate, 244 Timestamp: time.Now(), 245 TTL: time.Duration(router.DefaultAdvertTTL), 246 Events: events, 247 } 248 249 select { 250 case s.advertChan <- advert: 251 case <-s.exit: 252 close(s.advertChan) 253 return nil 254 } 255 256 return nil 257 } 258 259 // Status returns router status 260 func (s *svc) Status() router.Status { 261 s.Lock() 262 defer s.Unlock() 263 264 // check if its stopped 265 select { 266 case <-s.exit: 267 return router.Status{ 268 Code: router.Stopped, 269 Error: nil, 270 } 271 default: 272 // don't block 273 } 274 275 // check the remote router 276 rsp, err := s.router.Status(context.Background(), &pb.Request{}, s.callOpts...) 277 if err != nil { 278 return router.Status{ 279 Code: router.Error, 280 Error: err, 281 } 282 } 283 284 code := router.Running 285 var serr error 286 287 switch rsp.Status.Code { 288 case "running": 289 code = router.Running 290 case "advertising": 291 code = router.Advertising 292 case "stopped": 293 code = router.Stopped 294 case "error": 295 code = router.Error 296 } 297 298 if len(rsp.Status.Error) > 0 { 299 serr = errors.New(rsp.Status.Error) 300 } 301 302 return router.Status{ 303 Code: code, 304 Error: serr, 305 } 306 } 307 308 // Remote router cannot be stopped 309 func (s *svc) Stop() error { 310 s.Lock() 311 defer s.Unlock() 312 313 select { 314 case <-s.exit: 315 return nil 316 default: 317 close(s.exit) 318 } 319 320 return nil 321 } 322 323 // Lookup looks up routes in the routing table and returns them 324 func (s *svc) Lookup(q ...router.QueryOption) ([]router.Route, error) { 325 // call the router 326 query := router.NewQuery(q...) 327 328 resp, err := s.router.Lookup(context.Background(), &pb.LookupRequest{ 329 Query: &pb.Query{ 330 Service: query.Service, 331 Gateway: query.Gateway, 332 Network: query.Network, 333 }, 334 }, s.callOpts...) 335 336 // errored out 337 if err != nil { 338 return nil, err 339 } 340 341 routes := make([]router.Route, len(resp.Routes)) 342 for i, route := range resp.Routes { 343 routes[i] = router.Route{ 344 Service: route.Service, 345 Address: route.Address, 346 Gateway: route.Gateway, 347 Network: route.Network, 348 Link: route.Link, 349 Metric: route.Metric, 350 } 351 } 352 353 return routes, nil 354 } 355 356 // Watch returns a watcher which allows to track updates to the routing table 357 func (s *svc) Watch(opts ...router.WatchOption) (router.Watcher, error) { 358 rsp, err := s.router.Watch(context.Background(), &pb.WatchRequest{}, s.callOpts...) 359 if err != nil { 360 return nil, err 361 } 362 options := router.WatchOptions{ 363 Service: "*", 364 } 365 for _, o := range opts { 366 o(&options) 367 } 368 return newWatcher(rsp, options) 369 } 370 371 // Returns the router implementation 372 func (s *svc) String() string { 373 return "service" 374 }