2019-09-09 18:57:57 +03:00
|
|
|
// Package service uses the registry service
|
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
2020-01-30 14:39:00 +03:00
|
|
|
"github.com/micro/go-micro/v2/client"
|
|
|
|
"github.com/micro/go-micro/v2/client/grpc"
|
2020-05-14 21:38:56 +03:00
|
|
|
"github.com/micro/go-micro/v2/errors"
|
2020-01-30 14:39:00 +03:00
|
|
|
"github.com/micro/go-micro/v2/registry"
|
|
|
|
pb "github.com/micro/go-micro/v2/registry/service/proto"
|
2019-09-09 18:57:57 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// The default service name
|
2020-01-18 22:53:51 +03:00
|
|
|
DefaultService = "go.micro.registry"
|
2019-09-09 18:57:57 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
type serviceRegistry struct {
|
|
|
|
opts registry.Options
|
|
|
|
// name of the registry
|
|
|
|
name string
|
|
|
|
// address
|
|
|
|
address []string
|
2020-05-13 15:38:13 +03:00
|
|
|
// client to call registry
|
|
|
|
client pb.RegistryService
|
2019-09-09 18:57:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *serviceRegistry) callOpts() []client.CallOption {
|
|
|
|
var opts []client.CallOption
|
|
|
|
|
|
|
|
// set registry address
|
|
|
|
if len(s.address) > 0 {
|
|
|
|
opts = append(opts, client.WithAddress(s.address...))
|
|
|
|
}
|
|
|
|
|
|
|
|
// set timeout
|
|
|
|
if s.opts.Timeout > time.Duration(0) {
|
|
|
|
opts = append(opts, client.WithRequestTimeout(s.opts.Timeout))
|
|
|
|
}
|
|
|
|
|
|
|
|
return opts
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *serviceRegistry) Init(opts ...registry.Option) error {
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&s.opts)
|
|
|
|
}
|
2020-05-13 15:13:11 +03:00
|
|
|
|
2020-05-14 20:00:13 +03:00
|
|
|
if len(s.opts.Addrs) > 0 {
|
|
|
|
s.address = s.opts.Addrs
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:13:11 +03:00
|
|
|
// extract the client from the context, fallback to grpc
|
|
|
|
var cli client.Client
|
|
|
|
if c, ok := s.opts.Context.Value(clientKey{}).(client.Client); ok {
|
|
|
|
cli = c
|
|
|
|
} else {
|
|
|
|
cli = grpc.NewClient()
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:38:13 +03:00
|
|
|
s.client = pb.NewRegistryService(DefaultService, cli)
|
2020-05-13 15:13:11 +03:00
|
|
|
|
2019-09-09 18:57:57 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *serviceRegistry) Options() registry.Options {
|
|
|
|
return s.opts
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *serviceRegistry) Register(srv *registry.Service, opts ...registry.RegisterOption) error {
|
|
|
|
var options registry.RegisterOptions
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
2020-04-14 14:32:59 +03:00
|
|
|
if options.Context == nil {
|
|
|
|
options.Context = context.TODO()
|
|
|
|
}
|
2019-09-09 18:57:57 +03:00
|
|
|
|
2019-09-27 16:29:00 +03:00
|
|
|
// encode srv into protobuf and pack Register TTL into it
|
|
|
|
pbSrv := ToProto(srv)
|
|
|
|
pbSrv.Options.Ttl = int64(options.TTL.Seconds())
|
2019-09-25 18:20:42 +03:00
|
|
|
|
2019-09-09 18:57:57 +03:00
|
|
|
// register the service
|
2020-05-13 15:38:13 +03:00
|
|
|
_, err := s.client.Register(options.Context, pbSrv, s.callOpts()...)
|
2019-09-09 18:57:57 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-14 14:32:59 +03:00
|
|
|
func (s *serviceRegistry) Deregister(srv *registry.Service, opts ...registry.DeregisterOption) error {
|
|
|
|
var options registry.DeregisterOptions
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
|
|
|
if options.Context == nil {
|
|
|
|
options.Context = context.TODO()
|
|
|
|
}
|
|
|
|
|
2019-09-09 18:57:57 +03:00
|
|
|
// deregister the service
|
2020-05-13 15:38:13 +03:00
|
|
|
_, err := s.client.Deregister(options.Context, ToProto(srv), s.callOpts()...)
|
2019-09-09 18:57:57 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-14 14:32:59 +03:00
|
|
|
func (s *serviceRegistry) GetService(name string, opts ...registry.GetOption) ([]*registry.Service, error) {
|
|
|
|
var options registry.GetOptions
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
|
|
|
if options.Context == nil {
|
|
|
|
options.Context = context.TODO()
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:38:13 +03:00
|
|
|
rsp, err := s.client.GetService(options.Context, &pb.GetRequest{
|
2019-09-09 18:57:57 +03:00
|
|
|
Service: name,
|
|
|
|
}, s.callOpts()...)
|
|
|
|
|
2020-05-14 21:38:56 +03:00
|
|
|
if verr, ok := err.(*errors.Error); ok && verr.Code == 404 {
|
|
|
|
return nil, registry.ErrNotFound
|
|
|
|
} else if err != nil {
|
2019-09-09 18:57:57 +03:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-11-04 13:33:53 +03:00
|
|
|
services := make([]*registry.Service, 0, len(rsp.Services))
|
2019-09-09 18:57:57 +03:00
|
|
|
for _, service := range rsp.Services {
|
2019-09-09 19:20:17 +03:00
|
|
|
services = append(services, ToService(service))
|
2019-09-09 18:57:57 +03:00
|
|
|
}
|
|
|
|
return services, nil
|
|
|
|
}
|
|
|
|
|
2020-04-14 14:32:59 +03:00
|
|
|
func (s *serviceRegistry) ListServices(opts ...registry.ListOption) ([]*registry.Service, error) {
|
|
|
|
var options registry.ListOptions
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
|
|
|
if options.Context == nil {
|
|
|
|
options.Context = context.TODO()
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:38:13 +03:00
|
|
|
rsp, err := s.client.ListServices(options.Context, &pb.ListRequest{}, s.callOpts()...)
|
2019-09-09 18:57:57 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-11-04 13:33:53 +03:00
|
|
|
services := make([]*registry.Service, 0, len(rsp.Services))
|
2019-09-09 18:57:57 +03:00
|
|
|
for _, service := range rsp.Services {
|
2019-09-09 19:20:17 +03:00
|
|
|
services = append(services, ToService(service))
|
2019-09-09 18:57:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return services, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *serviceRegistry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) {
|
|
|
|
var options registry.WatchOptions
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
2020-04-14 14:32:59 +03:00
|
|
|
if options.Context == nil {
|
|
|
|
options.Context = context.TODO()
|
|
|
|
}
|
2019-09-09 18:57:57 +03:00
|
|
|
|
2020-05-13 15:38:13 +03:00
|
|
|
stream, err := s.client.Watch(options.Context, &pb.WatchRequest{
|
2019-09-09 18:57:57 +03:00
|
|
|
Service: options.Service,
|
|
|
|
}, s.callOpts()...)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return newWatcher(stream), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *serviceRegistry) String() string {
|
2020-01-18 22:53:51 +03:00
|
|
|
return "service"
|
2019-09-09 18:57:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewRegistry returns a new registry service client
|
|
|
|
func NewRegistry(opts ...registry.Option) registry.Registry {
|
|
|
|
var options registry.Options
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
|
|
|
|
2019-09-25 13:09:19 +03:00
|
|
|
// the registry address
|
|
|
|
addrs := options.Addrs
|
|
|
|
if len(addrs) == 0 {
|
|
|
|
addrs = []string{"127.0.0.1:8000"}
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:13:11 +03:00
|
|
|
if options.Context == nil {
|
|
|
|
options.Context = context.TODO()
|
|
|
|
}
|
2019-09-09 18:57:57 +03:00
|
|
|
|
2020-05-13 15:13:11 +03:00
|
|
|
// extract the client from the context, fallback to grpc
|
|
|
|
var cli client.Client
|
|
|
|
if c, ok := options.Context.Value(clientKey{}).(client.Client); ok {
|
|
|
|
cli = c
|
|
|
|
} else {
|
|
|
|
cli = grpc.NewClient()
|
|
|
|
}
|
2019-09-09 18:57:57 +03:00
|
|
|
|
2020-05-13 15:13:11 +03:00
|
|
|
// service name. TODO: accept option
|
2019-09-09 18:57:57 +03:00
|
|
|
name := DefaultService
|
|
|
|
|
|
|
|
return &serviceRegistry{
|
2020-05-13 15:38:13 +03:00
|
|
|
opts: options,
|
|
|
|
name: name,
|
|
|
|
address: addrs,
|
|
|
|
client: pb.NewRegistryService(name, cli),
|
2019-09-09 18:57:57 +03:00
|
|
|
}
|
|
|
|
}
|