Preserve cache in the face of failure
This commit is contained in:
parent
e2218c7819
commit
88dba1f50d
49
rcache.go
49
rcache.go
@ -36,7 +36,13 @@ type cache struct {
|
|||||||
ttls map[string]time.Time
|
ttls map[string]time.Time
|
||||||
watched map[string]bool
|
watched map[string]bool
|
||||||
|
|
||||||
|
// used to stop the cache
|
||||||
exit chan bool
|
exit chan bool
|
||||||
|
|
||||||
|
// status of the registry
|
||||||
|
// used to hold onto the cache
|
||||||
|
// in failure state
|
||||||
|
status error
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -50,6 +56,18 @@ func backoff(attempts int) time.Duration {
|
|||||||
return time.Duration(math.Pow(10, float64(attempts))) * time.Millisecond
|
return time.Duration(math.Pow(10, float64(attempts))) * time.Millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cache) getStatus() error {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
return c.status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cache) setStatus(err error) {
|
||||||
|
c.Lock()
|
||||||
|
c.status = err
|
||||||
|
c.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// isValid checks if the service is valid
|
// isValid checks if the service is valid
|
||||||
func (c *cache) isValid(services []*registry.Service, ttl time.Time) bool {
|
func (c *cache) isValid(services []*registry.Service, ttl time.Time) bool {
|
||||||
// no services exist
|
// no services exist
|
||||||
@ -81,6 +99,11 @@ func (c *cache) quit() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) del(service string) {
|
func (c *cache) del(service string) {
|
||||||
|
// don't blow away cache in error state
|
||||||
|
if err := c.getStatus(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// otherwise delete entries
|
||||||
delete(c.cache, service)
|
delete(c.cache, service)
|
||||||
delete(c.ttls, service)
|
delete(c.ttls, service)
|
||||||
}
|
}
|
||||||
@ -105,13 +128,26 @@ func (c *cache) get(service string) ([]*registry.Service, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get does the actual request for a service and cache it
|
// get does the actual request for a service and cache it
|
||||||
get := func(service string) ([]*registry.Service, error) {
|
get := func(service string, cached []*registry.Service) ([]*registry.Service, error) {
|
||||||
// ask the registry
|
// ask the registry
|
||||||
services, err := c.Registry.GetService(service)
|
services, err := c.Registry.GetService(service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// check the cache
|
||||||
|
if len(cached) > 0 {
|
||||||
|
// set the error status
|
||||||
|
c.setStatus(err)
|
||||||
|
// return the stale cache
|
||||||
|
return registry.Copy(cached), nil
|
||||||
|
}
|
||||||
|
// otherwise return error
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset the status
|
||||||
|
if c.getStatus(); err != nil {
|
||||||
|
c.setStatus(nil)
|
||||||
|
}
|
||||||
|
|
||||||
// cache results
|
// cache results
|
||||||
c.Lock()
|
c.Lock()
|
||||||
c.set(service, registry.Copy(services))
|
c.set(service, registry.Copy(services))
|
||||||
@ -129,7 +165,7 @@ func (c *cache) get(service string) ([]*registry.Service, error) {
|
|||||||
c.RUnlock()
|
c.RUnlock()
|
||||||
|
|
||||||
// get and return services
|
// get and return services
|
||||||
return get(service)
|
return get(service, services)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) set(service string, services []*registry.Service) {
|
func (c *cache) set(service string, services []*registry.Service) {
|
||||||
@ -283,6 +319,7 @@ func (c *cache) run(service string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d := backoff(a)
|
d := backoff(a)
|
||||||
|
c.setStatus(err)
|
||||||
|
|
||||||
if a > 3 {
|
if a > 3 {
|
||||||
log.Log("rcache: ", err, " backing off ", d)
|
log.Log("rcache: ", err, " backing off ", d)
|
||||||
@ -305,6 +342,7 @@ func (c *cache) run(service string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d := backoff(b)
|
d := backoff(b)
|
||||||
|
c.setStatus(err)
|
||||||
|
|
||||||
if b > 3 {
|
if b > 3 {
|
||||||
log.Log("rcache: ", err, " backing off ", d)
|
log.Log("rcache: ", err, " backing off ", d)
|
||||||
@ -348,6 +386,13 @@ func (c *cache) watch(w registry.Watcher) error {
|
|||||||
close(stop)
|
close(stop)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset the error status since we succeeded
|
||||||
|
if err := c.getStatus(); err != nil {
|
||||||
|
// reset status
|
||||||
|
c.setStatus(nil)
|
||||||
|
}
|
||||||
|
|
||||||
c.update(res)
|
c.update(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user