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 := ®istrySelector{ 118 so: sopts, 119 } 120 s.rc = s.newCache() 121 122 return s 123 }