@@ -15,7 +15,7 @@ type cacheSelector struct {
1515 ttl time.Duration
1616
1717 // registry cache
18- sync.Mutex
18+ sync.RWMutex
1919 cache map [string ][]* registry.Service
2020 ttls map [string ]time.Time
2121
@@ -81,17 +81,25 @@ func (c *cacheSelector) del(service string) {
8181}
8282
8383func (c * cacheSelector ) get (service string ) ([]* registry.Service , error ) {
84- c . Lock ()
85- defer c . Unlock ()
84+ // read lock
85+ c . RLock ()
8686
87- // watch service if not watched
88- if _ , ok := c .watched [service ]; ! ok {
89- go c .run (service )
90- c .watched [service ] = true
87+ // check the cache first
88+ services , ok := c .cache [service ]
89+ // get cache ttl
90+ ttl , kk := c .ttls [service ]
91+
92+ // got services && within ttl so return cache
93+ if ok && kk && time .Since (ttl ) < c .ttl {
94+ // make a copy
95+ cp := c .cp (services )
96+ // unlock the read
97+ c .RUnlock ()
98+ // return servics
99+ return cp , nil
91100 }
92101
93- // get does the actual request for a service
94- // it also caches it
102+ // get does the actual request for a service and cache it
95103 get := func (service string ) ([]* registry.Service , error ) {
96104 // ask the registry
97105 services , err := c .so .Registry .GetService (service )
@@ -100,43 +108,23 @@ func (c *cacheSelector) get(service string) ([]*registry.Service, error) {
100108 }
101109
102110 // cache results
111+ c .Lock ()
103112 c .set (service , c .cp (services ))
104- return services , nil
105- }
113+ c .Unlock ()
106114
107- // check the cache first
108- services , ok := c .cache [service ]
109-
110- // cache miss or no services
111- if ! ok || len (services ) == 0 {
112- return get (service )
113- }
114-
115- // got cache but lets check ttl
116- ttl , kk := c .ttls [service ]
117-
118- // within ttl so return cache
119- if kk && time .Since (ttl ) < c .ttl {
120- return c .cp (services ), nil
121- }
122-
123- // expired entry so get service
124- services , err := get (service )
125-
126- // no error then return error
127- if err == nil {
128115 return services , nil
129116 }
130117
131- // not found error then return
132- if err == registry . ErrNotFound {
133- return nil , selector . ErrNotFound
118+ // watch service if not watched
119+ if _ , ok := c . watched [ service ]; ! ok {
120+ go c . run ( service )
134121 }
135122
136- // other error
123+ // unlock the read lock
124+ c .RUnlock ()
137125
138- // return expired cache as last resort
139- return c . cp ( services ), nil
126+ // get and return services
127+ return get ( service )
140128}
141129
142130func (c * cacheSelector ) set (service string , services []* registry.Service ) {
@@ -257,6 +245,18 @@ func (c *cacheSelector) update(res *registry.Result) {
257245// reloads the watcher if Init is called
258246// and returns when Close is called
259247func (c * cacheSelector ) run (name string ) {
248+ // set watcher
249+ c .Lock ()
250+ c .watched [name ] = true
251+ c .Unlock ()
252+
253+ // delete watcher on exit
254+ defer func () {
255+ c .Lock ()
256+ delete (c .watched , name )
257+ c .Unlock ()
258+ }()
259+
260260 for {
261261 // exit early if already dead
262262 if c .quit () {
0 commit comments