diff --git a/cache/cache.go b/cache/cache.go index 898efc3..04d75ef 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -4,6 +4,7 @@ package cache import ( "crypto/sha256" "encoding/hex" + "strconv" "sync" "time" ) @@ -17,11 +18,11 @@ type CacheEntry struct { } type MemoryCache struct { - entries sync.Map - maxSize int64 + entries sync.Map + maxSize int64 currentSize int64 - ttl time.Duration - mu sync.Mutex + ttl time.Duration + mu sync.Mutex } func NewMemoryCache(maxSize int64, ttl time.Duration) *MemoryCache { @@ -31,20 +32,24 @@ func NewMemoryCache(maxSize int64, ttl time.Duration) *MemoryCache { } // 启动清理协程 - go mc.cleanup() + if ttl > 0 { + go mc.cleanup() + } return mc } +// Age 返回缓存条目的年龄(秒) func (e *CacheEntry) Age() string { - age := time.Since(e.Timestamp) + age := time.Since(e.CreatedAt) return strconv.FormatInt(int64(age.Seconds()), 10) } -func (mc *MemoryCache) Get(key string) (*CacheEntry, bool) { +// Get 获取缓存条目 +func (mc *MemoryCache) Get(key string) *CacheEntry { val, ok := mc.entries.Load(key) if !ok { - return nil, false + return nil } entry := val.(*CacheEntry) @@ -52,15 +57,26 @@ func (mc *MemoryCache) Get(key string) (*CacheEntry, bool) { // 检查是否过期 if time.Now().After(entry.ExpiresAt) { mc.Delete(key) - return nil, false + return nil } - return entry, true + return entry } +// Set 设置缓存条目 func (mc *MemoryCache) Set(key string, data []byte, headers map[string]string) bool { + // 如果禁用缓存(maxSize = 0),直接返回 + if mc.maxSize == 0 { + return false + } + size := int64(len(data)) + // 如果单个条目超过最大缓存大小,不缓存 + if size > mc.maxSize { + return false + } + mc.mu.Lock() defer mc.mu.Unlock() @@ -84,12 +100,19 @@ func (mc *MemoryCache) Set(key string, data []byte, headers map[string]string) b Size: size, } + // 如果 key 已存在,先删除旧的 + if oldVal, exists := mc.entries.Load(key); exists { + oldEntry := oldVal.(*CacheEntry) + mc.currentSize -= oldEntry.Size + } + mc.entries.Store(key, entry) mc.currentSize += size return true } +// Delete 删除缓存条目 func (mc *MemoryCache) Delete(key string) { val, ok := mc.entries.LoadAndDelete(key) if ok { @@ -100,11 +123,26 @@ func (mc *MemoryCache) Delete(key string) { } } +// Clear 清空所有缓存 +func (mc *MemoryCache) Clear() { + mc.mu.Lock() + defer mc.mu.Unlock() + + mc.entries.Range(func(key, value interface{}) bool { + mc.entries.Delete(key) + return true + }) + + mc.currentSize = 0 +} + +// GenerateKey 生成缓存键 func (mc *MemoryCache) GenerateKey(url string) string { hash := sha256.Sum256([]byte(url)) return hex.EncodeToString(hash[:]) } +// evictExpired 清理过期条目 func (mc *MemoryCache) evictExpired() { now := time.Now() mc.entries.Range(func(key, value interface{}) bool { @@ -117,6 +155,7 @@ func (mc *MemoryCache) evictExpired() { }) } +// evictOldest 清理最旧的条目 func (mc *MemoryCache) evictOldest(needed int64) { type entryWithKey struct { key string @@ -133,7 +172,7 @@ func (mc *MemoryCache) evictOldest(needed int64) { return true }) - // 按创建时间排序 + // 按创建时间排序(最旧的在前) for i := 0; i < len(entries)-1; i++ { for j := i + 1; j < len(entries); j++ { if entries[i].entry.CreatedAt.After(entries[j].entry.CreatedAt) { @@ -154,6 +193,7 @@ func (mc *MemoryCache) evictOldest(needed int64) { } } +// cleanup 定期清理过期条目 func (mc *MemoryCache) cleanup() { ticker := time.NewTicker(10 * time.Minute) defer ticker.Stop() @@ -165,6 +205,30 @@ func (mc *MemoryCache) cleanup() { } } +// Stats 返回缓存统计信息 +func (mc *MemoryCache) Stats() (entries int, size int64) { + count := 0 + mc.entries.Range(func(key, value interface{}) bool { + count++ + return true + }) + return count, mc.currentSize +} + +// GetStats 返回详细的缓存统计信息 +func (mc *MemoryCache) GetStats() map[string]interface{} { + entries, size := mc.Stats() + + return map[string]interface{}{ + "entries": entries, + "size": size, + "max_size": mc.maxSize, + "utilization": float64(size) / float64(mc.maxSize) * 100, + "ttl_seconds": int64(mc.ttl.Seconds()), + } +} + + func (mc *MemoryCache) Stats() (entries int, size int64) { count := 0 mc.entries.Range(func(key, value interface{}) bool {