| Index: server/auth/cache.go
|
| diff --git a/server/auth/cache.go b/server/auth/cache.go
|
| index 812e23f721e3fbe40d0fa9317e999ab14aaf4866..47a5c05e70fe3d8ced7b2ab12e15fccc2c9bb6f6 100644
|
| --- a/server/auth/cache.go
|
| +++ b/server/auth/cache.go
|
| @@ -15,10 +15,11 @@ import (
|
| "golang.org/x/net/context"
|
|
|
| "github.com/luci/luci-go/common/clock"
|
| + "github.com/luci/luci-go/common/data/caching/lru"
|
| "github.com/luci/luci-go/common/data/rand/mathrand"
|
| )
|
|
|
| -// delegationTokenCache is used to store delegation tokens in the global cache.
|
| +// delegationTokenCache is used to store delegation tokens in the cache.
|
| var delegationTokenCache = tokenCache{
|
| Kind: "delegation",
|
| Version: 2,
|
| @@ -26,9 +27,9 @@ var delegationTokenCache = tokenCache{
|
| MinAcceptedLifetime: 5 * time.Minute,
|
| }
|
|
|
| -// tokenCache knows how to keep tokens in the global cache.
|
| +// tokenCache knows how to keep tokens in the cache.
|
| //
|
| -// Uses Config.GlobalCache as a storage backend.
|
| +// Uses Config.Cache as a storage backend.
|
| //
|
| // It implements probabilistic early expiration to workaround cache stampede
|
| // problem for hot items, see Fetch.
|
| @@ -80,10 +81,10 @@ func (tc *tokenCache) Store(c context.Context, tok cachedToken) error {
|
| return err
|
| }
|
| cfg := GetConfig(c)
|
| - if cfg == nil || cfg.GlobalCache == nil {
|
| + if cfg == nil || cfg.Cache == nil {
|
| return ErrNotConfigured
|
| }
|
| - return cfg.GlobalCache.Set(c, tc.itemKey(tok.Key), blob, ttl)
|
| + return cfg.Cache.Set(c, tc.itemKey(tok.Key), blob, ttl)
|
| }
|
|
|
| // Fetch grabs cached token if it hasn't expired yet.
|
| @@ -94,11 +95,11 @@ func (tc *tokenCache) Store(c context.Context, tok cachedToken) error {
|
| // token, only the most unlucky one will refresh it.
|
| func (tc *tokenCache) Fetch(c context.Context, key string) (*cachedToken, error) {
|
| cfg := GetConfig(c)
|
| - if cfg == nil || cfg.GlobalCache == nil {
|
| + if cfg == nil || cfg.Cache == nil {
|
| return nil, ErrNotConfigured
|
| }
|
|
|
| - blob, err := cfg.GlobalCache.Get(c, tc.itemKey(key))
|
| + blob, err := cfg.Cache.Get(c, tc.itemKey(key))
|
| switch {
|
| case err != nil:
|
| return nil, err
|
| @@ -160,3 +161,50 @@ func (tc *tokenCache) unmarshal(blob []byte) (*cachedToken, error) {
|
| }
|
| return out, nil
|
| }
|
| +
|
| +type memoryCache struct {
|
| + cache *lru.Cache
|
| +}
|
| +
|
| +// MemoryCache creates a new in-memory Cache instance that is built on
|
| +// top of an LRU cache of the specified size.
|
| +func MemoryCache(size int) Cache {
|
| + return memoryCache{
|
| + cache: lru.New(size),
|
| + }
|
| +}
|
| +
|
| +func (mc memoryCache) Get(c context.Context, key string) ([]byte, error) {
|
| + var item *memoryCacheItem
|
| + now := clock.Now(c)
|
| + _ = mc.cache.Mutate(key, func(cur interface{}) interface{} {
|
| + if cur == nil {
|
| + return nil
|
| + }
|
| +
|
| + item = cur.(*memoryCacheItem)
|
| + if now.After(item.exp) {
|
| + // Cache item is too old, so expire it.
|
| + item = nil
|
| + }
|
| + return item
|
| + })
|
| + if item == nil {
|
| + // Cache miss (or expired).
|
| + return nil, nil
|
| + }
|
| + return item.value, nil
|
| +}
|
| +
|
| +func (mc memoryCache) Set(c context.Context, key string, value []byte, exp time.Duration) error {
|
| + mc.cache.Put(key, &memoryCacheItem{
|
| + value: value,
|
| + exp: clock.Now(c).Add(exp),
|
| + })
|
| + return nil
|
| +}
|
| +
|
| +type memoryCacheItem struct {
|
| + value []byte
|
| + exp time.Time
|
| +}
|
|
|