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  }