package cache import ( "encoding/json" "fmt" "time" "git.nakama.town/fmartingr/butterrobot/internal/db" ) // Cache provides a plugin-friendly interface to the cache system type Cache struct { db *db.Database pluginID string } // New creates a new Cache instance for a specific plugin func New(database *db.Database, pluginID string) *Cache { return &Cache{ db: database, pluginID: pluginID, } } // Get retrieves a value from the cache func (c *Cache) Get(key string, destination interface{}) error { // Create prefixed key fullKey := c.createKey(key) // Get from database value, err := c.db.CacheGet(fullKey) if err != nil { return err } // Unmarshal JSON into destination return json.Unmarshal([]byte(value), destination) } // Set stores a value in the cache with optional expiration func (c *Cache) Set(key string, value interface{}, expiration *time.Time) error { // Create prefixed key fullKey := c.createKey(key) // Marshal value to JSON jsonValue, err := json.Marshal(value) if err != nil { return fmt.Errorf("failed to marshal cache value: %w", err) } // Store in database return c.db.CacheSet(fullKey, string(jsonValue), expiration) } // SetWithTTL stores a value in the cache with a time-to-live duration func (c *Cache) SetWithTTL(key string, value interface{}, ttl time.Duration) error { expiration := time.Now().Add(ttl) return c.Set(key, value, &expiration) } // Delete removes a value from the cache func (c *Cache) Delete(key string) error { fullKey := c.createKey(key) return c.db.CacheDelete(fullKey) } // Exists checks if a key exists in the cache func (c *Cache) Exists(key string) (bool, error) { fullKey := c.createKey(key) _, err := c.db.CacheGet(fullKey) if err == db.ErrNotFound { return false, nil } if err != nil { return false, err } return true, nil } // createKey creates a prefixed cache key func (c *Cache) createKey(key string) string { return fmt.Sprintf("%s_%s", c.pluginID, key) }