// Package cache provides a Redis-backed cache with a small API mirroring the // in-memory cache it replaces (userInfoCache, processedMessages). package cache import ( "context" "encoding/json" "time" "github.com/redis/go-redis/v9" ) // Cache wraps a go-redis client for key/value storage with TTL. type Cache struct { rdb *redis.Client ctx context.Context } // New creates a Cache backed by the given Redis client. func New(rdb *redis.Client) *Cache { return &Cache{rdb: rdb, ctx: context.Background()} } // Set stores a value under key with an optional TTL (0 = no expiration). func (c *Cache) Set(key string, value interface{}, ttl time.Duration) error { b, err := json.Marshal(value) if err != nil { return err } return c.rdb.Set(c.ctx, key, b, ttl).Err() } // Get returns (value, true) if key exists, decoding into out. func (c *Cache) Get(key string, out interface{}) (bool, error) { data, err := c.rdb.Get(c.ctx, key).Bytes() if err != nil { if err == redis.Nil { return false, nil } return false, err } if out == nil { return true, nil } if err := json.Unmarshal(data, out); err != nil { return false, err } return true, nil } // Delete removes a key. func (c *Cache) Delete(key string) error { return c.rdb.Del(c.ctx, key).Err() } // SetNX atomically sets a key only if it does not already exist. // Returns true when the key was newly created. func (c *Cache) SetNX(key string, value interface{}, ttl time.Duration) (bool, error) { b, err := json.Marshal(value) if err != nil { return false, err } return c.rdb.SetNX(c.ctx, key, b, ttl).Result() }