package track1 import ( "context" "os" "time" "github.com/redis/go-redis/v9" ) // RedisCache is a Redis-based cache implementation // Use this in production for distributed caching type RedisCache struct { client *redis.Client ctx context.Context } // NewRedisCache creates a new Redis cache func NewRedisCache(redisURL string) (*RedisCache, error) { opts, err := redis.ParseURL(redisURL) if err != nil { return nil, err } client := redis.NewClient(opts) ctx := context.Background() // Test connection if err := client.Ping(ctx).Err(); err != nil { return nil, err } return &RedisCache{ client: client, ctx: ctx, }, nil } // NewRedisCacheFromClient creates a new Redis cache from an existing client func NewRedisCacheFromClient(client *redis.Client) *RedisCache { return &RedisCache{ client: client, ctx: context.Background(), } } // Get retrieves a value from cache func (c *RedisCache) Get(key string) ([]byte, error) { val, err := c.client.Get(c.ctx, key).Bytes() if err == redis.Nil { return nil, ErrCacheMiss } if err != nil { return nil, err } return val, nil } // Set stores a value in cache with TTL func (c *RedisCache) Set(key string, value []byte, ttl time.Duration) error { return c.client.Set(c.ctx, key, value, ttl).Err() } // Delete removes a key from cache func (c *RedisCache) Delete(key string) error { return c.client.Del(c.ctx, key).Err() } // Clear clears all cache keys (use with caution) func (c *RedisCache) Clear() error { return c.client.FlushDB(c.ctx).Err() } // Close closes the Redis connection func (c *RedisCache) Close() error { return c.client.Close() } // NewCache creates a cache based on environment // Returns Redis cache if REDIS_URL is set, otherwise in-memory cache func NewCache() (Cache, error) { redisURL := os.Getenv("REDIS_URL") if redisURL != "" { return NewRedisCache(redisURL) } return NewInMemoryCache(), nil }