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  }