go-micro.dev/v5@v5.12.0/selector/default.go (about)

     1  package selector
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/pkg/errors"
     8  
     9  	"go-micro.dev/v5/registry"
    10  	"go-micro.dev/v5/registry/cache"
    11  )
    12  
    13  type registrySelector struct {
    14  	so Options
    15  	rc cache.Cache
    16  	mu sync.RWMutex
    17  }
    18  
    19  func (c *registrySelector) newCache() cache.Cache {
    20  	opts := make([]cache.Option, 0, 1)
    21  
    22  	if c.so.Context != nil {
    23  		if t, ok := c.so.Context.Value("selector_ttl").(time.Duration); ok {
    24  			opts = append(opts, cache.WithTTL(t))
    25  		}
    26  	}
    27  
    28  	return cache.New(c.so.Registry, opts...)
    29  }
    30  
    31  func (c *registrySelector) Init(opts ...Option) error {
    32  	c.mu.Lock()
    33  	defer c.mu.Unlock()
    34  
    35  	for _, o := range opts {
    36  		o(&c.so)
    37  	}
    38  
    39  	c.rc.Stop()
    40  	c.rc = c.newCache()
    41  
    42  	return nil
    43  }
    44  
    45  func (c *registrySelector) Options() Options {
    46  	return c.so
    47  }
    48  
    49  func (c *registrySelector) Select(service string, opts ...SelectOption) (Next, error) {
    50  	c.mu.RLock()
    51  	defer c.mu.RUnlock()
    52  
    53  	sopts := SelectOptions{
    54  		Strategy: c.so.Strategy,
    55  	}
    56  
    57  	for _, opt := range opts {
    58  		opt(&sopts)
    59  	}
    60  
    61  	// get the service
    62  	// try the cache first
    63  	// if that fails go directly to the registry
    64  	services, err := c.rc.GetService(service)
    65  	if err != nil {
    66  		if errors.Is(err, registry.ErrNotFound) {
    67  			return nil, ErrNotFound
    68  		}
    69  
    70  		return nil, err
    71  	}
    72  
    73  	// apply the filters
    74  	for _, filter := range sopts.Filters {
    75  		services = filter(services)
    76  	}
    77  
    78  	// if there's nothing left, return
    79  	if len(services) == 0 {
    80  		return nil, ErrNoneAvailable
    81  	}
    82  
    83  	return sopts.Strategy(services), nil
    84  }
    85  
    86  func (c *registrySelector) Mark(service string, node *registry.Node, err error) {
    87  }
    88  
    89  func (c *registrySelector) Reset(service string) {
    90  }
    91  
    92  // Close stops the watcher and destroys the cache.
    93  func (c *registrySelector) Close() error {
    94  	c.rc.Stop()
    95  
    96  	return nil
    97  }
    98  
    99  func (c *registrySelector) String() string {
   100  	return "registry"
   101  }
   102  
   103  // NewSelector creates a new default selector.
   104  func NewSelector(opts ...Option) Selector {
   105  	sopts := Options{
   106  		Strategy: Random,
   107  	}
   108  
   109  	for _, opt := range opts {
   110  		opt(&sopts)
   111  	}
   112  
   113  	if sopts.Registry == nil {
   114  		sopts.Registry = registry.DefaultRegistry
   115  	}
   116  
   117  	s := &registrySelector{
   118  		so: sopts,
   119  	}
   120  	s.rc = s.newCache()
   121  
   122  	return s
   123  }