mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-12-06 22:36:23 +00:00
148 lines
3.9 KiB
Go
148 lines
3.9 KiB
Go
package cache
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// Cache is the main cache manager that wraps a Provider.
|
|
type Cache struct {
|
|
provider Provider
|
|
}
|
|
|
|
// NewCache creates a new cache manager with the specified provider.
|
|
func NewCache(provider Provider) *Cache {
|
|
return &Cache{
|
|
provider: provider,
|
|
}
|
|
}
|
|
|
|
// Get retrieves and deserializes a value from the cache.
|
|
func (c *Cache) Get(ctx context.Context, key string, dest interface{}) error {
|
|
data, exists := c.provider.Get(ctx, key)
|
|
if !exists {
|
|
return fmt.Errorf("key not found: %s", key)
|
|
}
|
|
|
|
if err := json.Unmarshal(data, dest); err != nil {
|
|
return fmt.Errorf("failed to deserialize: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetBytes retrieves raw bytes from the cache.
|
|
func (c *Cache) GetBytes(ctx context.Context, key string) ([]byte, error) {
|
|
data, exists := c.provider.Get(ctx, key)
|
|
if !exists {
|
|
return nil, fmt.Errorf("key not found: %s", key)
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
// Set serializes and stores a value in the cache with the specified TTL.
|
|
func (c *Cache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error {
|
|
data, err := json.Marshal(value)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to serialize: %w", err)
|
|
}
|
|
|
|
return c.provider.Set(ctx, key, data, ttl)
|
|
}
|
|
|
|
// SetBytes stores raw bytes in the cache with the specified TTL.
|
|
func (c *Cache) SetBytes(ctx context.Context, key string, value []byte, ttl time.Duration) error {
|
|
return c.provider.Set(ctx, key, value, ttl)
|
|
}
|
|
|
|
// Delete removes a key from the cache.
|
|
func (c *Cache) Delete(ctx context.Context, key string) error {
|
|
return c.provider.Delete(ctx, key)
|
|
}
|
|
|
|
// DeleteByPattern removes all keys matching the pattern.
|
|
func (c *Cache) DeleteByPattern(ctx context.Context, pattern string) error {
|
|
return c.provider.DeleteByPattern(ctx, pattern)
|
|
}
|
|
|
|
// Clear removes all items from the cache.
|
|
func (c *Cache) Clear(ctx context.Context) error {
|
|
return c.provider.Clear(ctx)
|
|
}
|
|
|
|
// Exists checks if a key exists in the cache.
|
|
func (c *Cache) Exists(ctx context.Context, key string) bool {
|
|
return c.provider.Exists(ctx, key)
|
|
}
|
|
|
|
// Stats returns statistics about the cache.
|
|
func (c *Cache) Stats(ctx context.Context) (*CacheStats, error) {
|
|
return c.provider.Stats(ctx)
|
|
}
|
|
|
|
// Close closes the cache and releases any resources.
|
|
func (c *Cache) Close() error {
|
|
return c.provider.Close()
|
|
}
|
|
|
|
// GetOrSet retrieves a value from cache, or sets it if it doesn't exist.
|
|
// The loader function is called only if the key is not found in cache.
|
|
func (c *Cache) GetOrSet(ctx context.Context, key string, dest interface{}, ttl time.Duration, loader func() (interface{}, error)) error {
|
|
// Try to get from cache first
|
|
err := c.Get(ctx, key, dest)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
// Load the value
|
|
value, err := loader()
|
|
if err != nil {
|
|
return fmt.Errorf("loader failed: %w", err)
|
|
}
|
|
|
|
// Store in cache
|
|
if err := c.Set(ctx, key, value, ttl); err != nil {
|
|
return fmt.Errorf("failed to cache value: %w", err)
|
|
}
|
|
|
|
// Populate dest with the loaded value
|
|
data, err := json.Marshal(value)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to serialize loaded value: %w", err)
|
|
}
|
|
|
|
if err := json.Unmarshal(data, dest); err != nil {
|
|
return fmt.Errorf("failed to deserialize loaded value: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Remember is a convenience function that caches the result of a function call.
|
|
// It's similar to GetOrSet but returns the value directly.
|
|
func (c *Cache) Remember(ctx context.Context, key string, ttl time.Duration, loader func() (interface{}, error)) (interface{}, error) {
|
|
// Try to get from cache first as bytes
|
|
data, err := c.GetBytes(ctx, key)
|
|
if err == nil {
|
|
var result interface{}
|
|
if err := json.Unmarshal(data, &result); err == nil {
|
|
return result, nil
|
|
}
|
|
}
|
|
|
|
// Load the value
|
|
value, err := loader()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("loader failed: %w", err)
|
|
}
|
|
|
|
// Store in cache
|
|
if err := c.Set(ctx, key, value, ttl); err != nil {
|
|
return nil, fmt.Errorf("failed to cache value: %w", err)
|
|
}
|
|
|
|
return value, nil
|
|
}
|