github.com/argoproj/argo-cd/v3@v3.2.1/util/cache/twolevelclient.go (about) 1 package cache 2 3 import ( 4 "context" 5 "time" 6 7 log "github.com/sirupsen/logrus" 8 ) 9 10 // NewTwoLevelClient creates cache client that proxies requests to given external cache and tries to minimize 11 // number of requests to external client by storing cache entries in local in-memory cache. 12 func NewTwoLevelClient(client CacheClient, inMemoryExpiration time.Duration) *twoLevelClient { 13 return &twoLevelClient{inMemoryCache: NewInMemoryCache(inMemoryExpiration), externalCache: client} 14 } 15 16 type twoLevelClient struct { 17 inMemoryCache *InMemoryCache 18 externalCache CacheClient 19 } 20 21 func (c *twoLevelClient) Rename(oldKey string, newKey string, expiration time.Duration) error { 22 err := c.inMemoryCache.Rename(oldKey, newKey, expiration) 23 if err != nil { 24 log.Warnf("Failed to move key '%s' in in-memory cache: %v", oldKey, err) 25 } 26 return c.externalCache.Rename(oldKey, newKey, expiration) 27 } 28 29 // Set stores the given value in both in-memory and external cache. 30 // Skip storing the value in external cache if the same value already exists in memory to avoid requesting external cache. 31 func (c *twoLevelClient) Set(item *Item) error { 32 has, err := c.inMemoryCache.HasSame(item.Key, item.Object) 33 if has { 34 return nil 35 } 36 if err != nil { 37 log.Warnf("Failed to check key '%s' in in-memory cache: %v", item.Key, err) 38 } 39 err = c.inMemoryCache.Set(item) 40 if err != nil { 41 log.Warnf("Failed to save key '%s' in in-memory cache: %v", item.Key, err) 42 } 43 return c.externalCache.Set(item) 44 } 45 46 // Get returns cache value from in-memory cache if it present. Otherwise loads it from external cache and persists 47 // in memory to avoid future requests to external cache. 48 func (c *twoLevelClient) Get(key string, obj any) error { 49 err := c.inMemoryCache.Get(key, obj) 50 if err == nil { 51 return nil 52 } 53 54 err = c.externalCache.Get(key, obj) 55 if err == nil { 56 _ = c.inMemoryCache.Set(&Item{Key: key, Object: obj}) 57 } 58 return err 59 } 60 61 // Delete deletes cache for given key in both in-memory and external cache. 62 func (c *twoLevelClient) Delete(key string) error { 63 err := c.inMemoryCache.Delete(key) 64 if err != nil { 65 return err 66 } 67 return c.externalCache.Delete(key) 68 } 69 70 func (c *twoLevelClient) OnUpdated(ctx context.Context, key string, callback func() error) error { 71 return c.externalCache.OnUpdated(ctx, key, callback) 72 } 73 74 func (c *twoLevelClient) NotifyUpdated(key string) error { 75 return c.externalCache.NotifyUpdated(key) 76 }