Spaces:
Running
Running
restructure repo into production layout; add whatsapp-service, tests, ddl, docs, scripts; scrub hardcoded secrets
83d6851 | // 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() | |
| } | |