github.com/micro/go-micro/v2@v2.9.1/registry/service/service.go (about) 1 // Package service uses the registry service 2 package service 3 4 import ( 5 "context" 6 "time" 7 8 "github.com/micro/go-micro/v2/client" 9 "github.com/micro/go-micro/v2/client/grpc" 10 "github.com/micro/go-micro/v2/errors" 11 "github.com/micro/go-micro/v2/registry" 12 pb "github.com/micro/go-micro/v2/registry/service/proto" 13 ) 14 15 var ( 16 // The default service name 17 DefaultService = "go.micro.registry" 18 ) 19 20 type serviceRegistry struct { 21 opts registry.Options 22 // name of the registry 23 name string 24 // address 25 address []string 26 // client to call registry 27 client pb.RegistryService 28 } 29 30 func (s *serviceRegistry) callOpts() []client.CallOption { 31 var opts []client.CallOption 32 33 // set registry address 34 if len(s.address) > 0 { 35 opts = append(opts, client.WithAddress(s.address...)) 36 } 37 38 // set timeout 39 if s.opts.Timeout > time.Duration(0) { 40 opts = append(opts, client.WithRequestTimeout(s.opts.Timeout)) 41 } 42 43 return opts 44 } 45 46 func (s *serviceRegistry) Init(opts ...registry.Option) error { 47 for _, o := range opts { 48 o(&s.opts) 49 } 50 51 if len(s.opts.Addrs) > 0 { 52 s.address = s.opts.Addrs 53 } 54 55 // extract the client from the context, fallback to grpc 56 var cli client.Client 57 if c, ok := s.opts.Context.Value(clientKey{}).(client.Client); ok { 58 cli = c 59 } else { 60 cli = grpc.NewClient() 61 } 62 63 s.client = pb.NewRegistryService(DefaultService, cli) 64 65 return nil 66 } 67 68 func (s *serviceRegistry) Options() registry.Options { 69 return s.opts 70 } 71 72 func (s *serviceRegistry) Register(srv *registry.Service, opts ...registry.RegisterOption) error { 73 var options registry.RegisterOptions 74 for _, o := range opts { 75 o(&options) 76 } 77 if options.Context == nil { 78 options.Context = context.TODO() 79 } 80 81 // encode srv into protobuf and pack Register TTL into it 82 pbSrv := ToProto(srv) 83 pbSrv.Options.Ttl = int64(options.TTL.Seconds()) 84 85 // register the service 86 _, err := s.client.Register(options.Context, pbSrv, s.callOpts()...) 87 if err != nil { 88 return err 89 } 90 91 return nil 92 } 93 94 func (s *serviceRegistry) Deregister(srv *registry.Service, opts ...registry.DeregisterOption) error { 95 var options registry.DeregisterOptions 96 for _, o := range opts { 97 o(&options) 98 } 99 if options.Context == nil { 100 options.Context = context.TODO() 101 } 102 103 // deregister the service 104 _, err := s.client.Deregister(options.Context, ToProto(srv), s.callOpts()...) 105 if err != nil { 106 return err 107 } 108 return nil 109 } 110 111 func (s *serviceRegistry) GetService(name string, opts ...registry.GetOption) ([]*registry.Service, error) { 112 var options registry.GetOptions 113 for _, o := range opts { 114 o(&options) 115 } 116 if options.Context == nil { 117 options.Context = context.TODO() 118 } 119 120 rsp, err := s.client.GetService(options.Context, &pb.GetRequest{ 121 Service: name, 122 }, s.callOpts()...) 123 124 if verr, ok := err.(*errors.Error); ok && verr.Code == 404 { 125 return nil, registry.ErrNotFound 126 } else if err != nil { 127 return nil, err 128 } 129 130 services := make([]*registry.Service, 0, len(rsp.Services)) 131 for _, service := range rsp.Services { 132 services = append(services, ToService(service)) 133 } 134 return services, nil 135 } 136 137 func (s *serviceRegistry) ListServices(opts ...registry.ListOption) ([]*registry.Service, error) { 138 var options registry.ListOptions 139 for _, o := range opts { 140 o(&options) 141 } 142 if options.Context == nil { 143 options.Context = context.TODO() 144 } 145 146 rsp, err := s.client.ListServices(options.Context, &pb.ListRequest{}, s.callOpts()...) 147 if err != nil { 148 return nil, err 149 } 150 151 services := make([]*registry.Service, 0, len(rsp.Services)) 152 for _, service := range rsp.Services { 153 services = append(services, ToService(service)) 154 } 155 156 return services, nil 157 } 158 159 func (s *serviceRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { 160 var options registry.WatchOptions 161 for _, o := range opts { 162 o(&options) 163 } 164 if options.Context == nil { 165 options.Context = context.TODO() 166 } 167 168 stream, err := s.client.Watch(options.Context, &pb.WatchRequest{ 169 Service: options.Service, 170 }, s.callOpts()...) 171 172 if err != nil { 173 return nil, err 174 } 175 176 return newWatcher(stream), nil 177 } 178 179 func (s *serviceRegistry) String() string { 180 return "service" 181 } 182 183 // NewRegistry returns a new registry service client 184 func NewRegistry(opts ...registry.Option) registry.Registry { 185 var options registry.Options 186 for _, o := range opts { 187 o(&options) 188 } 189 190 // the registry address 191 addrs := options.Addrs 192 if len(addrs) == 0 { 193 addrs = []string{"127.0.0.1:8000"} 194 } 195 196 if options.Context == nil { 197 options.Context = context.TODO() 198 } 199 200 // extract the client from the context, fallback to grpc 201 var cli client.Client 202 if c, ok := options.Context.Value(clientKey{}).(client.Client); ok { 203 cli = c 204 } else { 205 cli = grpc.NewClient() 206 } 207 208 // service name. TODO: accept option 209 name := DefaultService 210 211 return &serviceRegistry{ 212 opts: options, 213 name: name, 214 address: addrs, 215 client: pb.NewRegistryService(name, cli), 216 } 217 }