github.com/argoproj/argo-cd@v1.8.7/util/cache/cache.go (about) 1 package cache 2 3 import ( 4 "context" 5 "fmt" 6 "math" 7 "os" 8 "time" 9 10 "github.com/go-redis/redis/v8" 11 "github.com/spf13/cobra" 12 13 "github.com/argoproj/argo-cd/common" 14 "github.com/argoproj/argo-cd/util/env" 15 ) 16 17 const ( 18 // envRedisPassword is a env variable name which stores redis password 19 envRedisPassword = "REDIS_PASSWORD" 20 // envRedisRetryCount is a env variable name which stores redis retry count 21 envRedisRetryCount = "REDIS_RETRY_COUNT" 22 // defaultRedisRetryCount holds default number of retries 23 defaultRedisRetryCount = 3 24 ) 25 26 func NewCache(client CacheClient) *Cache { 27 return &Cache{client} 28 } 29 30 // AddCacheFlagsToCmd adds flags which control caching to the specified command 31 func AddCacheFlagsToCmd(cmd *cobra.Command, opts ...func(client *redis.Client)) func() (*Cache, error) { 32 redisAddress := "" 33 sentinelAddresses := make([]string, 0) 34 sentinelMaster := "" 35 redisDB := 0 36 var defaultCacheExpiration time.Duration 37 38 cmd.Flags().StringVar(&redisAddress, "redis", "", "Redis server hostname and port (e.g. argocd-redis:6379). ") 39 cmd.Flags().IntVar(&redisDB, "redisdb", 0, "Redis database.") 40 cmd.Flags().StringArrayVar(&sentinelAddresses, "sentinel", []string{}, "Redis sentinel hostname and port (e.g. argocd-redis-ha-announce-0:6379). ") 41 cmd.Flags().StringVar(&sentinelMaster, "sentinelmaster", "master", "Redis sentinel master group name.") 42 cmd.Flags().DurationVar(&defaultCacheExpiration, "default-cache-expiration", 24*time.Hour, "Cache expiration default") 43 return func() (*Cache, error) { 44 password := os.Getenv(envRedisPassword) 45 maxRetries := env.ParseNumFromEnv(envRedisRetryCount, defaultRedisRetryCount, 0, math.MaxInt32) 46 if len(sentinelAddresses) > 0 { 47 client := redis.NewFailoverClient(&redis.FailoverOptions{ 48 MasterName: sentinelMaster, 49 SentinelAddrs: sentinelAddresses, 50 DB: redisDB, 51 Password: password, 52 MaxRetries: maxRetries, 53 }) 54 for i := range opts { 55 opts[i](client) 56 } 57 return NewCache(NewRedisCache(client, defaultCacheExpiration)), nil 58 } 59 60 if redisAddress == "" { 61 redisAddress = common.DefaultRedisAddr 62 } 63 client := redis.NewClient(&redis.Options{ 64 Addr: redisAddress, 65 Password: password, 66 DB: redisDB, 67 MaxRetries: maxRetries, 68 }) 69 for i := range opts { 70 opts[i](client) 71 } 72 return NewCache(NewRedisCache(client, defaultCacheExpiration)), nil 73 } 74 } 75 76 // Cache provides strongly types methods to store and retrieve values from shared cache 77 type Cache struct { 78 client CacheClient 79 } 80 81 func (c *Cache) GetClient() CacheClient { 82 return c.client 83 } 84 85 func (c *Cache) SetClient(client CacheClient) { 86 c.client = client 87 } 88 89 func (c *Cache) SetItem(key string, item interface{}, expiration time.Duration, delete bool) error { 90 key = fmt.Sprintf("%s|%s", key, common.CacheVersion) 91 if delete { 92 return c.client.Delete(key) 93 } else { 94 if item == nil { 95 return fmt.Errorf("cannot set item to nil for key %s", key) 96 } 97 return c.client.Set(&Item{Object: item, Key: key, Expiration: expiration}) 98 } 99 } 100 101 func (c *Cache) GetItem(key string, item interface{}) error { 102 if item == nil { 103 return fmt.Errorf("cannot get item into a nil for key %s", key) 104 } 105 key = fmt.Sprintf("%s|%s", key, common.CacheVersion) 106 return c.client.Get(key, item) 107 } 108 109 func (c *Cache) OnUpdated(ctx context.Context, key string, callback func() error) error { 110 return c.client.OnUpdated(ctx, fmt.Sprintf("%s|%s", key, common.CacheVersion), callback) 111 } 112 113 func (c *Cache) NotifyUpdated(key string) error { 114 return c.client.NotifyUpdated(fmt.Sprintf("%s|%s", key, common.CacheVersion)) 115 }