91 lines
1.6 KiB
Go
91 lines
1.6 KiB
Go
package gateway
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// InMemoryCache is a simple in-memory cache
|
|
// In production, use Redis for distributed caching
|
|
type InMemoryCache struct {
|
|
items map[string]*cacheItem
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
// cacheItem represents a cached item
|
|
type cacheItem struct {
|
|
value []byte
|
|
expiresAt time.Time
|
|
}
|
|
|
|
// NewInMemoryCache creates a new in-memory cache
|
|
func NewInMemoryCache() *InMemoryCache {
|
|
cache := &InMemoryCache{
|
|
items: make(map[string]*cacheItem),
|
|
}
|
|
|
|
// Start cleanup goroutine
|
|
go cache.cleanup()
|
|
|
|
return cache
|
|
}
|
|
|
|
// Get retrieves a value from cache
|
|
func (c *InMemoryCache) Get(key string) ([]byte, error) {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
item, exists := c.items[key]
|
|
if !exists {
|
|
return nil, ErrCacheMiss
|
|
}
|
|
|
|
if time.Now().After(item.expiresAt) {
|
|
return nil, ErrCacheMiss
|
|
}
|
|
|
|
return item.value, nil
|
|
}
|
|
|
|
// Set stores a value in cache with TTL
|
|
func (c *InMemoryCache) Set(key string, value []byte, ttl time.Duration) error {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
c.items[key] = &cacheItem{
|
|
value: value,
|
|
expiresAt: time.Now().Add(ttl),
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// cleanup removes expired items
|
|
func (c *InMemoryCache) cleanup() {
|
|
ticker := time.NewTicker(1 * time.Minute)
|
|
defer ticker.Stop()
|
|
|
|
for range ticker.C {
|
|
c.mu.Lock()
|
|
now := time.Now()
|
|
for key, item := range c.items {
|
|
if now.After(item.expiresAt) {
|
|
delete(c.items, key)
|
|
}
|
|
}
|
|
c.mu.Unlock()
|
|
}
|
|
}
|
|
|
|
// ErrCacheMiss is returned when a cache key is not found
|
|
var ErrCacheMiss = &CacheError{Message: "cache miss"}
|
|
|
|
// CacheError represents a cache error
|
|
type CacheError struct {
|
|
Message string
|
|
}
|
|
|
|
func (e *CacheError) Error() string {
|
|
return e.Message
|
|
}
|