go-micro.dev/v5@v5.12.0/server/rpc_events.go (about) 1 package server 2 3 import ( 4 "context" 5 "fmt" 6 7 "go-micro.dev/v5/broker" 8 raw "go-micro.dev/v5/codec/bytes" 9 log "go-micro.dev/v5/logger" 10 "go-micro.dev/v5/metadata" 11 "go-micro.dev/v5/transport/headers" 12 ) 13 14 // HandleEvent handles inbound messages to the service directly. 15 // These events are a result of registering to the topic with the service name. 16 // TODO: handle requests from an event. We won't send a response. 17 func (s *rpcServer) HandleEvent(subscriber string) func(e broker.Event) error { 18 return func(e broker.Event) error { 19 // formatting horrible cruft 20 msg := e.Message() 21 22 if msg.Header == nil { 23 msg.Header = make(map[string]string) 24 } 25 26 contentType, ok := msg.Header["Content-Type"] 27 if !ok || len(contentType) == 0 { 28 msg.Header["Content-Type"] = DefaultContentType 29 contentType = DefaultContentType 30 } 31 32 cf, err := s.newCodec(contentType) 33 if err != nil { 34 return err 35 } 36 37 header := make(map[string]string, len(msg.Header)) 38 for k, v := range msg.Header { 39 header[k] = v 40 } 41 42 // create context 43 ctx := metadata.NewContext(context.Background(), header) 44 45 // TODO: inspect message header for Micro-Service & Micro-Topic 46 rpcMsg := &rpcMessage{ 47 topic: msg.Header[headers.Message], 48 contentType: contentType, 49 payload: &raw.Frame{Data: msg.Body}, 50 codec: cf, 51 header: msg.Header, 52 body: msg.Body, 53 } 54 55 // if the router is present then execute it 56 r := Router(s.router) 57 if s.opts.Router != nil { 58 // create a wrapped function 59 // create a wrapped function 60 handler := func(ctx context.Context, msg Message) error { 61 return s.opts.Router.ProcessMessage(ctx, subscriber, msg) 62 } 63 64 // execute the wrapper for it 65 for i := len(s.opts.SubWrappers); i > 0; i-- { 66 handler = s.opts.SubWrappers[i-1](handler) 67 } 68 69 // set the router 70 r = rpcRouter{m: func(ctx context.Context, _ string, msg Message) error { 71 return handler(ctx, msg) 72 }} 73 } 74 75 return r.ProcessMessage(ctx, subscriber, rpcMsg) 76 } 77 } 78 79 func (s *rpcServer) NewSubscriber(topic string, sb interface{}, opts ...SubscriberOption) Subscriber { 80 return s.router.NewSubscriber(topic, sb, opts...) 81 } 82 83 func (s *rpcServer) Subscribe(sb Subscriber) error { 84 s.Lock() 85 defer s.Unlock() 86 87 sub, ok := sb.(*subscriber) 88 if !ok { 89 return fmt.Errorf("invalid subscriber: expected *subscriber") 90 } 91 if len(sub.handlers) == 0 { 92 return fmt.Errorf("invalid subscriber: no handler functions") 93 } 94 95 if err := validateSubscriber(sub); err != nil { 96 return err 97 } 98 99 // append to subscribers 100 // subs := s.subscribers[sub.Topic()] 101 // subs = append(subs, sub) 102 // router.subscribers[sub.Topic()] = subs 103 104 s.subscribers[sb] = nil 105 106 return nil 107 } 108 109 // subscribeServer will subscribe the server to the topic with its own name. 110 func (s *rpcServer) subscribeServer(config Options) error { 111 if s.opts.Router != nil && s.subscriber == nil { 112 sub, err := s.opts.Broker.Subscribe(config.Name, s.HandleEvent(config.Name)) 113 if err != nil { 114 return err 115 } 116 117 // Save the subscriber 118 s.subscriber = sub 119 } 120 121 return nil 122 } 123 124 // reSubscribe itterates over subscribers and re-subscribes then. 125 func (s *rpcServer) reSubscribe(config Options) { 126 for sb := range s.subscribers { 127 if s.subscribers[sb] != nil { 128 continue 129 } 130 // If we've already created a broker subscription for this topic 131 // (from a different Subscriber entry) then don't create another 132 // broker.Subscribe. We still need to register the subscriber with 133 // the router so it receives dispatched messages. 134 var already bool 135 for other, subs := range s.subscribers { 136 if other.Topic() == sb.Topic() && subs != nil { 137 already = true 138 break 139 } 140 } 141 if already { 142 // register with router only 143 if err := s.router.Subscribe(sb); err != nil { 144 config.Logger.Logf(log.WarnLevel, "Unable to subscribing to topic: %s, error: %s", sb.Topic(), err) 145 continue 146 } 147 // mark this subscriber as having no broker subscription 148 s.subscribers[sb] = nil 149 continue 150 } 151 var opts []broker.SubscribeOption 152 if queue := sb.Options().Queue; len(queue) > 0 { 153 opts = append(opts, broker.Queue(queue)) 154 } 155 156 if ctx := sb.Options().Context; ctx != nil { 157 opts = append(opts, broker.SubscribeContext(ctx)) 158 } 159 160 if !sb.Options().AutoAck { 161 opts = append(opts, broker.DisableAutoAck()) 162 } 163 164 config.Logger.Logf(log.InfoLevel, "Subscribing to topic: %s", sb.Topic()) 165 sub, err := config.Broker.Subscribe(sb.Topic(), s.HandleEvent(sb.Topic()), opts...) 166 if err != nil { 167 config.Logger.Logf(log.WarnLevel, "Unable to subscribing to topic: %s, error: %s", sb.Topic(), err) 168 continue 169 } 170 err = s.router.Subscribe(sb) 171 if err != nil { 172 config.Logger.Logf(log.WarnLevel, "Unable to subscribing to topic: %s, error: %s", sb.Topic(), err) 173 sub.Unsubscribe() 174 continue 175 } 176 s.subscribers[sb] = []broker.Subscriber{sub} 177 } 178 }