github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/server/mucp/rpc_server.go (about) 1 // Copyright 2020 Asim Aslam 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Original source: github.com/micro/go-micro/v3/server/mucp/rpc_server.go 16 17 package mucp 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 "net" 24 "runtime/debug" 25 "sort" 26 "strconv" 27 "strings" 28 "sync" 29 "time" 30 31 "github.com/tickoalcantara12/micro/v3/service/broker" 32 "github.com/tickoalcantara12/micro/v3/service/context/metadata" 33 "github.com/tickoalcantara12/micro/v3/service/logger" 34 "github.com/tickoalcantara12/micro/v3/service/network/transport" 35 "github.com/tickoalcantara12/micro/v3/service/registry" 36 "github.com/tickoalcantara12/micro/v3/service/server" 37 "github.com/tickoalcantara12/micro/v3/util/addr" 38 "github.com/tickoalcantara12/micro/v3/util/backoff" 39 "github.com/tickoalcantara12/micro/v3/util/codec" 40 raw "github.com/tickoalcantara12/micro/v3/util/codec/bytes" 41 mnet "github.com/tickoalcantara12/micro/v3/util/net" 42 "github.com/tickoalcantara12/micro/v3/util/socket" 43 ) 44 45 type rpcServer struct { 46 router *router 47 exit chan chan error 48 49 sync.RWMutex 50 opts server.Options 51 handlers map[string]server.Handler 52 subscribers map[server.Subscriber][]broker.Subscriber 53 // marks the serve as started 54 started bool 55 // used for first registration 56 registered bool 57 // subscribe to service name 58 subscriber broker.Subscriber 59 // graceful exit 60 wg *sync.WaitGroup 61 62 rsvc *registry.Service 63 } 64 65 var ( 66 log = logger.NewHelper(logger.DefaultLogger).WithFields(map[string]interface{}{"service": "server"}) 67 ) 68 69 func wait(ctx context.Context) *sync.WaitGroup { 70 if ctx == nil { 71 return nil 72 } 73 wg, ok := ctx.Value("wait").(*sync.WaitGroup) 74 if !ok { 75 return nil 76 } 77 return wg 78 } 79 80 func newServer(opts ...server.Option) server.Server { 81 options := newOptions(opts...) 82 router := newRpcRouter() 83 router.hdlrWrappers = options.HdlrWrappers 84 router.subWrappers = options.SubWrappers 85 86 return &rpcServer{ 87 opts: options, 88 router: router, 89 handlers: make(map[string]server.Handler), 90 subscribers: make(map[server.Subscriber][]broker.Subscriber), 91 exit: make(chan chan error), 92 wg: wait(options.Context), 93 } 94 } 95 96 // HandleEvent handles inbound messages to the service directly 97 // TODO: handle requests from an event. We won't send a response. 98 func (s *rpcServer) HandleEvent(msg *broker.Message) error { 99 if msg.Header == nil { 100 // create empty map in case of headers empty to avoid panic later 101 msg.Header = make(map[string]string) 102 } 103 104 // get codec 105 ct := msg.Header["Content-Type"] 106 107 // default content type 108 if len(ct) == 0 { 109 msg.Header["Content-Type"] = DefaultContentType 110 ct = DefaultContentType 111 } 112 113 // get codec 114 cf, err := s.newCodec(ct) 115 if err != nil { 116 return err 117 } 118 119 // copy headers 120 hdr := make(map[string]string, len(msg.Header)) 121 for k, v := range msg.Header { 122 hdr[k] = v 123 } 124 125 // create context 126 ctx := metadata.NewContext(context.Background(), hdr) 127 128 // TODO: inspect message header 129 // Micro-Service means a request 130 // Micro-Topic means a message 131 132 rpcMsg := &rpcMessage{ 133 topic: msg.Header["Micro-Topic"], 134 contentType: ct, 135 payload: &raw.Frame{Data: msg.Body}, 136 codec: cf, 137 header: msg.Header, 138 body: msg.Body, 139 } 140 141 // existing router 142 r := server.Router(s.router) 143 144 // if the router is present then execute it 145 if s.opts.Router != nil { 146 // create a wrapped function 147 handler := s.opts.Router.ProcessMessage 148 149 // execute the wrapper for it 150 for i := len(s.opts.SubWrappers); i > 0; i-- { 151 handler = s.opts.SubWrappers[i-1](handler) 152 } 153 154 // set the router 155 r = rpcRouter{m: handler} 156 } 157 158 return r.ProcessMessage(ctx, rpcMsg) 159 } 160 161 // ServeConn serves a single connection 162 func (s *rpcServer) ServeConn(sock transport.Socket) { 163 // streams are multiplexed on Micro-Stream or Micro-Id header 164 pool := socket.NewPool() 165 166 // get global waitgroup 167 s.Lock() 168 gg := s.wg 169 s.Unlock() 170 171 // waitgroup to wait for processing to finish 172 wg := &waitGroup{ 173 gg: gg, 174 } 175 176 defer func() { 177 // wait till done 178 wg.Wait() 179 180 // close all the sockets for this connection 181 pool.Close() 182 183 // close underlying socket 184 sock.Close() 185 186 // recover any panics 187 if r := recover(); r != nil { 188 if logger.V(logger.ErrorLevel, log) { 189 log.Error("panic recovered: ", r) 190 log.Error(string(debug.Stack())) 191 } 192 } 193 }() 194 195 for { 196 var msg transport.Message 197 // process inbound messages one at a time 198 if err := sock.Recv(&msg); err != nil { 199 return 200 } 201 202 // check the message header for 203 // Micro-Service is a request 204 // Micro-Topic is a message 205 if t := msg.Header["Micro-Topic"]; len(t) > 0 { 206 // TODO: handle the error event 207 if err := s.HandleEvent(newMessage(msg)); err != nil { 208 msg.Header["Micro-Error"] = err.Error() 209 } 210 // write back some 200 211 if err := sock.Send(&transport.Message{ 212 Header: msg.Header, 213 }); err != nil { 214 break 215 } 216 // we're done 217 continue 218 } 219 220 // business as usual 221 222 // use Micro-Stream as the stream identifier 223 // in the event its blank we'll always process 224 // on the same socket 225 id := msg.Header["Micro-Stream"] 226 227 // if there's no stream id then its a standard request 228 // use the Micro-Id 229 if len(id) == 0 { 230 id = msg.Header["Micro-Id"] 231 } 232 233 // check stream id 234 var stream bool 235 236 if v := getHeader("Micro-Stream", msg.Header); len(v) > 0 { 237 stream = true 238 } 239 240 // check if we have an existing socket 241 psock, ok := pool.Get(id) 242 243 // if we don't have a socket and its a stream 244 if !ok && stream { 245 // check if its a last stream EOS error 246 err := msg.Header["Micro-Error"] 247 if err == lastStreamResponseError.Error() { 248 pool.Release(psock) 249 continue 250 } 251 } 252 253 // got an existing socket already 254 if ok { 255 // we're starting processing 256 wg.Add(1) 257 258 // pass the message to that existing socket 259 if err := psock.Accept(&msg); err != nil { 260 // release the socket if there's an error 261 pool.Release(psock) 262 } 263 264 // done waiting 265 wg.Done() 266 267 // continue to the next message 268 continue 269 } 270 271 // no socket was found so its new 272 // set the local and remote values 273 psock.SetLocal(sock.Local()) 274 psock.SetRemote(sock.Remote()) 275 276 // load the socket with the current message 277 psock.Accept(&msg) 278 279 // now walk the usual path 280 281 // we use this Timeout header to set a server deadline 282 to := msg.Header["Timeout"] 283 // we use this Content-Type header to identify the codec needed 284 ct := msg.Header["Content-Type"] 285 286 // copy the message headers 287 hdr := make(map[string]string, len(msg.Header)) 288 for k, v := range msg.Header { 289 hdr[k] = v 290 } 291 292 // set local/remote ips 293 hdr["Local"] = sock.Local() 294 hdr["Remote"] = sock.Remote() 295 296 // create new context with the metadata 297 ctx := metadata.NewContext(context.Background(), hdr) 298 299 // set the timeout from the header if we have it 300 if len(to) > 0 { 301 if n, err := strconv.ParseUint(to, 10, 64); err == nil { 302 var cancel context.CancelFunc 303 ctx, cancel = context.WithTimeout(ctx, time.Duration(n)) 304 defer cancel() 305 } 306 } 307 308 // if there's no content type default it 309 if len(ct) == 0 { 310 msg.Header["Content-Type"] = DefaultContentType 311 ct = DefaultContentType 312 } 313 314 // setup old protocol 315 cf := setupProtocol(&msg) 316 317 // no legacy codec needed 318 if cf == nil { 319 var err error 320 // try get a new codec 321 if cf, err = s.newCodec(ct); err != nil { 322 // no codec found so send back an error 323 sock.Send(&transport.Message{ 324 Header: map[string]string{ 325 "Content-Type": "text/plain", 326 }, 327 Body: []byte(err.Error()), 328 }) 329 330 // release the socket we just created 331 pool.Release(psock) 332 // now continue 333 continue 334 } 335 } 336 337 // create a new rpc codec based on the pseudo socket and codec 338 rcodec := newRpcCodec(&msg, psock, cf) 339 // check the protocol as well 340 protocol := rcodec.String() 341 342 // internal request 343 request := &rpcRequest{ 344 service: getHeader("Micro-Service", msg.Header), 345 method: getHeader("Micro-Method", msg.Header), 346 endpoint: getHeader("Micro-Endpoint", msg.Header), 347 contentType: ct, 348 codec: rcodec, 349 header: msg.Header, 350 body: msg.Body, 351 socket: psock, 352 stream: stream, 353 } 354 355 // internal response 356 response := &rpcResponse{ 357 header: make(map[string]string), 358 socket: psock, 359 codec: rcodec, 360 } 361 362 // set router 363 r := server.Router(s.router) 364 365 // if not nil use the router specified 366 if s.opts.Router != nil { 367 // create a wrapped function 368 handler := func(ctx context.Context, req server.Request, rsp interface{}) error { 369 return s.opts.Router.ServeRequest(ctx, req, rsp.(server.Response)) 370 } 371 372 // execute the wrapper for it 373 for i := len(s.opts.HdlrWrappers); i > 0; i-- { 374 handler = s.opts.HdlrWrappers[i-1](handler) 375 } 376 377 // set the router 378 r = rpcRouter{h: handler} 379 } 380 381 // wait for two coroutines to exit 382 // serve the request and process the outbound messages 383 wg.Add(2) 384 385 // process the outbound messages from the socket 386 go func(id string, psock *socket.Socket) { 387 defer func() { 388 // TODO: don't hack this but if its grpc just break out of the stream 389 // We do this because the underlying connection is h2 and its a stream 390 switch protocol { 391 case "grpc": 392 sock.Close() 393 } 394 // release the socket 395 pool.Release(psock) 396 // signal we're done 397 wg.Done() 398 399 // recover any panics for outbound process 400 if r := recover(); r != nil { 401 if logger.V(logger.ErrorLevel, log) { 402 log.Error("panic recovered: ", r) 403 log.Error(string(debug.Stack())) 404 } 405 } 406 }() 407 408 for { 409 // get the message from our internal handler/stream 410 m := new(transport.Message) 411 if err := psock.Process(m); err != nil { 412 return 413 } 414 415 // send the message back over the socket 416 if err := sock.Send(m); err != nil { 417 return 418 } 419 } 420 }(id, psock) 421 422 // serve the request in a go routine as this may be a stream 423 go func(id string, psock *socket.Socket) { 424 defer func() { 425 // release the socket 426 pool.Release(psock) 427 // signal we're done 428 wg.Done() 429 430 // recover any panics for call handler 431 if r := recover(); r != nil { 432 log.Error("panic recovered: ", r) 433 log.Error(string(debug.Stack())) 434 } 435 }() 436 437 // serve the actual request using the request router 438 if serveRequestError := r.ServeRequest(ctx, request, response); serveRequestError != nil { 439 // write an error response 440 writeError := rcodec.Write(&codec.Message{ 441 Header: msg.Header, 442 Error: serveRequestError.Error(), 443 Type: codec.Error, 444 }, nil) 445 446 // if the server request is an EOS error we let the socket know 447 // sometimes the socket is already closed on the other side, so we can ignore that error 448 alreadyClosed := serveRequestError == lastStreamResponseError && writeError == io.EOF 449 450 // could not write error response 451 if writeError != nil && !alreadyClosed { 452 log.Debugf("rpc: unable to write error response: %v", writeError) 453 } 454 } 455 }(id, psock) 456 } 457 } 458 459 func (s *rpcServer) newCodec(contentType string) (codec.NewCodec, error) { 460 if cf, ok := s.opts.Codecs[contentType]; ok { 461 return cf, nil 462 } 463 if cf, ok := DefaultCodecs[contentType]; ok { 464 return cf, nil 465 } 466 return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) 467 } 468 469 func (s *rpcServer) Options() server.Options { 470 s.RLock() 471 opts := s.opts 472 s.RUnlock() 473 return opts 474 } 475 476 func (s *rpcServer) Init(opts ...server.Option) error { 477 s.Lock() 478 defer s.Unlock() 479 480 for _, opt := range opts { 481 opt(&s.opts) 482 } 483 // update router if its the default 484 if s.opts.Router == nil { 485 r := newRpcRouter() 486 r.hdlrWrappers = s.opts.HdlrWrappers 487 r.serviceMap = s.router.serviceMap 488 r.subWrappers = s.opts.SubWrappers 489 s.router = r 490 } 491 492 s.rsvc = nil 493 494 return nil 495 } 496 497 func (s *rpcServer) NewHandler(h interface{}, opts ...server.HandlerOption) server.Handler { 498 return s.router.NewHandler(h, opts...) 499 } 500 501 func (s *rpcServer) Handle(h server.Handler) error { 502 s.Lock() 503 defer s.Unlock() 504 505 if err := s.router.Handle(h); err != nil { 506 return err 507 } 508 509 s.handlers[h.Name()] = h 510 511 return nil 512 } 513 514 func (s *rpcServer) NewSubscriber(topic string, sb interface{}, opts ...server.SubscriberOption) server.Subscriber { 515 return s.router.NewSubscriber(topic, sb, opts...) 516 } 517 518 func (s *rpcServer) Subscribe(sb server.Subscriber) error { 519 s.Lock() 520 defer s.Unlock() 521 522 if err := s.router.Subscribe(sb); err != nil { 523 return err 524 } 525 526 s.subscribers[sb] = nil 527 return nil 528 } 529 530 func (s *rpcServer) Register() error { 531 s.RLock() 532 rsvc := s.rsvc 533 config := s.Options() 534 s.RUnlock() 535 536 // only register if it exists or is not noop 537 if config.Registry == nil || config.Registry.String() == "noop" { 538 return nil 539 } 540 541 regFunc := func(service *registry.Service) error { 542 // create registry options 543 rOpts := []registry.RegisterOption{ 544 registry.RegisterTTL(config.RegisterTTL), 545 registry.RegisterDomain(s.opts.Namespace), 546 } 547 548 var regErr error 549 550 for i := 0; i < 3; i++ { 551 // attempt to register 552 if err := config.Registry.Register(service, rOpts...); err != nil { 553 // set the error 554 regErr = err 555 // backoff then retry 556 time.Sleep(backoff.Do(i + 1)) 557 continue 558 } 559 // success so nil error 560 regErr = nil 561 break 562 } 563 564 return regErr 565 } 566 567 // have we registered before? 568 if rsvc != nil { 569 if err := regFunc(rsvc); err != nil { 570 return err 571 } 572 return nil 573 } 574 575 var err error 576 var advt, host, port string 577 var cacheService bool 578 579 // check the advertise address first 580 // if it exists then use it, otherwise 581 // use the address 582 if len(config.Advertise) > 0 { 583 advt = config.Advertise 584 } else { 585 advt = config.Address 586 } 587 588 if cnt := strings.Count(advt, ":"); cnt >= 1 { 589 // ipv6 address in format [host]:port or ipv4 host:port 590 host, port, err = net.SplitHostPort(advt) 591 if err != nil { 592 return err 593 } 594 } else { 595 host = advt 596 } 597 598 if ip := net.ParseIP(host); ip != nil { 599 cacheService = true 600 } 601 602 addr, err := addr.Extract(host) 603 if err != nil { 604 return err 605 } 606 607 // make copy of metadata 608 md := metadata.Copy(config.Metadata) 609 610 // mq-rpc(eg. nats) doesn't need the port. its addr is queue name. 611 if port != "" { 612 addr = mnet.HostPort(addr, port) 613 } 614 615 // register service 616 node := ®istry.Node{ 617 Id: config.Name + "-" + config.Id, 618 Address: addr, 619 Metadata: md, 620 } 621 622 node.Metadata["transport"] = config.Transport.String() 623 node.Metadata["broker"] = config.Broker.String() 624 node.Metadata["server"] = s.String() 625 node.Metadata["registry"] = config.Registry.String() 626 node.Metadata["protocol"] = "mucp" 627 628 s.RLock() 629 630 // Maps are ordered randomly, sort the keys for consistency 631 var handlerList []string 632 for n, e := range s.handlers { 633 // Only advertise non internal handlers 634 if !e.Options().Internal { 635 handlerList = append(handlerList, n) 636 } 637 } 638 639 sort.Strings(handlerList) 640 641 var subscriberList []server.Subscriber 642 for e := range s.subscribers { 643 // Only advertise non internal subscribers 644 if !e.Options().Internal { 645 subscriberList = append(subscriberList, e) 646 } 647 } 648 649 sort.Slice(subscriberList, func(i, j int) bool { 650 return subscriberList[i].Topic() > subscriberList[j].Topic() 651 }) 652 653 endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList)) 654 655 for _, n := range handlerList { 656 endpoints = append(endpoints, s.handlers[n].Endpoints()...) 657 } 658 659 for _, e := range subscriberList { 660 endpoints = append(endpoints, e.Endpoints()...) 661 } 662 663 service := ®istry.Service{ 664 Name: config.Name, 665 Version: config.Version, 666 Nodes: []*registry.Node{node}, 667 Endpoints: endpoints, 668 } 669 670 // get registered value 671 registered := s.registered 672 673 s.RUnlock() 674 675 if !registered { 676 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 677 log.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id) 678 } 679 } 680 681 // register the service 682 if err := regFunc(service); err != nil { 683 return err 684 } 685 686 // already registered? don't need to register subscribers 687 if registered { 688 return nil 689 } 690 691 s.Lock() 692 defer s.Unlock() 693 694 // set what we're advertising 695 s.opts.Advertise = addr 696 697 // router can exchange messages 698 if s.opts.Router != nil { 699 // subscribe to the topic with own name 700 sub, err := s.opts.Broker.Subscribe(config.Name, s.HandleEvent) 701 if err != nil { 702 return err 703 } 704 705 // save the subscriber 706 s.subscriber = sub 707 } 708 709 // subscribe for all of the subscribers 710 for sb := range s.subscribers { 711 var opts []broker.SubscribeOption 712 if queue := sb.Options().Queue; len(queue) > 0 { 713 opts = append(opts, broker.Queue(queue)) 714 } 715 716 if cx := sb.Options().Context; cx != nil { 717 opts = append(opts, broker.SubscribeContext(cx)) 718 } 719 720 sub, err := config.Broker.Subscribe(sb.Topic(), s.HandleEvent, opts...) 721 if err != nil { 722 return err 723 } 724 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 725 log.Infof("Subscribing to topic: %s", sub.Topic()) 726 } 727 s.subscribers[sb] = []broker.Subscriber{sub} 728 } 729 if cacheService { 730 s.rsvc = service 731 } 732 s.registered = true 733 734 return nil 735 } 736 737 func (s *rpcServer) Deregister() error { 738 var err error 739 var advt, host, port string 740 741 s.RLock() 742 config := s.Options() 743 s.RUnlock() 744 745 // only register if it exists or is not noop 746 if config.Registry == nil || config.Registry.String() == "noop" { 747 return nil 748 } 749 750 // check the advertise address first 751 // if it exists then use it, otherwise 752 // use the address 753 if len(config.Advertise) > 0 { 754 advt = config.Advertise 755 } else { 756 advt = config.Address 757 } 758 759 if cnt := strings.Count(advt, ":"); cnt >= 1 { 760 // ipv6 address in format [host]:port or ipv4 host:port 761 host, port, err = net.SplitHostPort(advt) 762 if err != nil { 763 return err 764 } 765 } else { 766 host = advt 767 } 768 769 addr, err := addr.Extract(host) 770 if err != nil { 771 return err 772 } 773 774 // mq-rpc(eg. nats) doesn't need the port. its addr is queue name. 775 if port != "" { 776 addr = mnet.HostPort(addr, port) 777 } 778 779 node := ®istry.Node{ 780 Id: config.Name + "-" + config.Id, 781 Address: addr, 782 } 783 784 service := ®istry.Service{ 785 Name: config.Name, 786 Version: config.Version, 787 Nodes: []*registry.Node{node}, 788 } 789 790 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 791 log.Infof("Registry [%s] Deregistering node: %s", config.Registry.String(), node.Id) 792 } 793 if err := config.Registry.Deregister(service, registry.DeregisterDomain(s.opts.Namespace)); err != nil { 794 return err 795 } 796 797 s.Lock() 798 s.rsvc = nil 799 800 if !s.registered { 801 s.Unlock() 802 return nil 803 } 804 805 s.registered = false 806 807 // close the subscriber 808 if s.subscriber != nil { 809 s.subscriber.Unsubscribe() 810 s.subscriber = nil 811 } 812 813 for sb, subs := range s.subscribers { 814 for _, sub := range subs { 815 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 816 log.Infof("Unsubscribing %s from topic: %s", node.Id, sub.Topic()) 817 } 818 sub.Unsubscribe() 819 } 820 s.subscribers[sb] = nil 821 } 822 823 s.Unlock() 824 return nil 825 } 826 827 func (s *rpcServer) Start() error { 828 s.RLock() 829 if s.started { 830 s.RUnlock() 831 return nil 832 } 833 s.RUnlock() 834 835 config := s.Options() 836 837 // start listening on the transport 838 ts, err := config.Transport.Listen(config.Address) 839 if err != nil { 840 return err 841 } 842 843 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 844 log.Infof("Transport [%s] Listening on %s", config.Transport.String(), ts.Addr()) 845 } 846 847 // swap address 848 s.Lock() 849 addr := s.opts.Address 850 s.opts.Address = ts.Addr() 851 s.Unlock() 852 853 bname := config.Broker.String() 854 855 // connect to the broker 856 if err := config.Broker.Connect(); err != nil { 857 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 858 log.Errorf("Broker [%s] connect error: %v", bname, err) 859 } 860 return err 861 } 862 863 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 864 log.Infof("Broker [%s] Connected to %s", bname, config.Broker.Address()) 865 } 866 867 // use RegisterCheck func before register 868 if err = s.opts.RegisterCheck(s.opts.Context); err != nil { 869 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 870 log.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, err) 871 } 872 } else { 873 // announce self to the world 874 if err = s.Register(); err != nil { 875 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 876 log.Errorf("Server %s-%s register error: %s", config.Name, config.Id, err) 877 } 878 } 879 } 880 881 exit := make(chan bool) 882 883 go func() { 884 for { 885 // listen for connections 886 err := ts.Accept(s.ServeConn) 887 888 // TODO: listen for messages 889 // msg := broker.Exchange(service).Consume() 890 891 select { 892 // check if we're supposed to exit 893 case <-exit: 894 return 895 // check the error and backoff 896 default: 897 if err != nil { 898 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 899 log.Errorf("Accept error: %v", err) 900 } 901 time.Sleep(time.Second) 902 continue 903 } 904 } 905 906 // no error just exit 907 return 908 } 909 }() 910 911 go func() { 912 t := new(time.Ticker) 913 914 // only process if it exists 915 if s.opts.RegisterInterval > time.Duration(0) { 916 // new ticker 917 t = time.NewTicker(s.opts.RegisterInterval) 918 } 919 920 // return error chan 921 var ch chan error 922 923 Loop: 924 for { 925 select { 926 // register self on interval 927 case <-t.C: 928 s.RLock() 929 registered := s.registered 930 s.RUnlock() 931 rerr := s.opts.RegisterCheck(s.opts.Context) 932 if rerr != nil && registered { 933 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 934 log.Errorf("Server %s-%s register check error: %s, deregister it", config.Name, config.Id, rerr) 935 } 936 // deregister self in case of error 937 if err := s.Deregister(); err != nil { 938 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 939 log.Errorf("Server %s-%s deregister error: %s", config.Name, config.Id, err) 940 } 941 } 942 } else if rerr != nil && !registered { 943 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 944 log.Errorf("Server %s-%s register check error: %s", config.Name, config.Id, rerr) 945 } 946 continue 947 } 948 if err := s.Register(); err != nil { 949 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 950 log.Errorf("Server %s-%s register error: %s", config.Name, config.Id, err) 951 } 952 } 953 // wait for exit 954 case ch = <-s.exit: 955 t.Stop() 956 close(exit) 957 break Loop 958 } 959 } 960 961 s.RLock() 962 registered := s.registered 963 s.RUnlock() 964 if registered { 965 // deregister self 966 if err := s.Deregister(); err != nil { 967 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 968 log.Errorf("Server %s-%s deregister error: %s", config.Name, config.Id, err) 969 } 970 } 971 } 972 973 s.Lock() 974 swg := s.wg 975 s.Unlock() 976 977 // wait for requests to finish 978 if swg != nil { 979 swg.Wait() 980 } 981 982 // close transport listener 983 ch <- ts.Close() 984 985 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 986 log.Infof("Broker [%s] Disconnected from %s", bname, config.Broker.Address()) 987 } 988 // disconnect the broker 989 if err := config.Broker.Disconnect(); err != nil { 990 if logger.V(logger.ErrorLevel, logger.DefaultLogger) { 991 log.Errorf("Broker [%s] Disconnect error: %v", bname, err) 992 } 993 } 994 995 // swap back address 996 s.Lock() 997 s.opts.Address = addr 998 s.Unlock() 999 }() 1000 1001 // mark the server as started 1002 s.Lock() 1003 s.started = true 1004 s.Unlock() 1005 1006 return nil 1007 } 1008 1009 func (s *rpcServer) Stop() error { 1010 s.RLock() 1011 if !s.started { 1012 s.RUnlock() 1013 return nil 1014 } 1015 s.RUnlock() 1016 1017 ch := make(chan error) 1018 s.exit <- ch 1019 1020 err := <-ch 1021 s.Lock() 1022 s.started = false 1023 s.Unlock() 1024 1025 return err 1026 } 1027 1028 func (s *rpcServer) String() string { 1029 return "mucp" 1030 }