diff --git a/agent/cache/cache.go b/agent/cache/cache.go index 71213d4016..5162f0fa9e 100644 --- a/agent/cache/cache.go +++ b/agent/cache/cache.go @@ -227,42 +227,43 @@ func (c *Cache) Get(t string, r Request) (interface{}, ResultMeta, error) { // getEntryLocked retrieves a cache entry and checks if it is ready to be // returned given the other parameters. It reads from entries and the caller // has to issue a read lock if necessary. -func (c *Cache) getEntryLocked(tEntry typeEntry, key string, maxAge time.Duration, revalidate bool, minIndex uint64) (bool, bool, cacheEntry) { +func (c *Cache) getEntryLocked( + tEntry typeEntry, + key string, + maxAge time.Duration, + revalidate bool, + minIndex uint64, +) (entryExists bool, entryValid bool, entry cacheEntry) { entry, ok := c.entries[key] - cacheHit := false - - if !ok { - return ok, cacheHit, entry + if !entry.Valid { + return ok, false, entry } - // Check if we have a hit - cacheHit = ok && entry.Valid - - supportsBlocking := tEntry.Type.SupportsBlocking() - // Check index is not specified or lower than value, or the type doesn't // support blocking. - if cacheHit && supportsBlocking && - minIndex > 0 && minIndex >= entry.Index { + if tEntry.Type.SupportsBlocking() && minIndex > 0 && minIndex >= entry.Index { // MinIndex was given and matches or is higher than current value so we // ignore the cache and fallthrough to blocking on a new value below. - cacheHit = false + return true, false, entry } // Check MaxAge is not exceeded if this is not a background refreshing type // and MaxAge was specified. - if cacheHit && !tEntry.Opts.Refresh && maxAge > 0 && - !entry.FetchedAt.IsZero() && maxAge < time.Since(entry.FetchedAt) { - cacheHit = false + if !tEntry.Opts.Refresh && maxAge > 0 && entryExceedsMaxAge(maxAge, entry) { + return true, false, entry } - // Check if we are requested to revalidate. If so the first time round the + // Check if re-validate is requested. If so the first time round the // loop is not a hit but subsequent ones should be treated normally. - if cacheHit && !tEntry.Opts.Refresh && revalidate { - cacheHit = false + if !tEntry.Opts.Refresh && revalidate { + return true, false, entry } - return ok, cacheHit, entry + return true, true, entry +} + +func entryExceedsMaxAge(maxAge time.Duration, entry cacheEntry) bool { + return !entry.FetchedAt.IsZero() && maxAge < time.Since(entry.FetchedAt) } // getWithIndex implements the main Get functionality but allows internal @@ -289,10 +290,10 @@ func (c *Cache) getWithIndex(tEntry typeEntry, r Request, minIndex uint64) (inte RETRY_GET: // Get the current value c.entriesLock.RLock() - _, cacheHit, entry := c.getEntryLocked(tEntry, key, info.MaxAge, info.MustRevalidate && first, minIndex) + _, entryValid, entry := c.getEntryLocked(tEntry, key, info.MaxAge, info.MustRevalidate && first, minIndex) c.entriesLock.RUnlock() - if cacheHit { + if entryValid { meta := ResultMeta{Index: entry.Index} if first { metrics.IncrCounter([]string{"consul", "cache", tEntry.Name, "hit"}, 1) @@ -401,11 +402,11 @@ func (c *Cache) fetch(tEntry typeEntry, key string, r Request, allowNew bool, at // We acquire a write lock because we may have to set Fetching to true. c.entriesLock.Lock() defer c.entriesLock.Unlock() - ok, cacheHit, entry := c.getEntryLocked(tEntry, key, info.MaxAge, info.MustRevalidate && !ignoreRevalidation, minIndex) + ok, entryValid, entry := c.getEntryLocked(tEntry, key, info.MaxAge, info.MustRevalidate && !ignoreRevalidation, minIndex) // This handles the case where a fetch succeeded after checking for its existence in // getWithIndex. This ensures that we don't miss updates. - if ok && cacheHit && !ignoreExisting { + if ok && entryValid && !ignoreExisting { ch := make(chan struct{}) close(ch) return ch, nil