x-movie/server/cache.go

158 lines
3.2 KiB
Go
Raw Normal View History

package main
import (
"sync"
"time"
)
// CacheItem 缓存项
type CacheItem struct {
data []byte
timestamp time.Time
size int
}
// ThumbnailCache 缩略图缓存
type ThumbnailCache struct {
items map[string]*CacheItem
mu sync.RWMutex
maxSize int64 // 最大缓存大小(字节)
usedSize int64 // 已使用大小
ttl time.Duration // 缓存过期时间
}
// NewThumbnailCache 创建新的缩略图缓存
func NewThumbnailCache(maxSizeMB int, ttlMinutes int) *ThumbnailCache {
return &ThumbnailCache{
items: make(map[string]*CacheItem),
maxSize: int64(maxSizeMB) * 1024 * 1024,
ttl: time.Duration(ttlMinutes) * time.Minute,
}
}
// Get 获取缓存项
func (c *ThumbnailCache) Get(key string) ([]byte, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
item, exists := c.items[key]
if !exists {
return nil, false
}
// 检查是否过期
if time.Since(item.timestamp) > c.ttl {
go c.Remove(key)
return nil, false
}
return item.data, true
}
// Set 设置缓存项
func (c *ThumbnailCache) Set(key string, data []byte) {
c.mu.Lock()
defer c.mu.Unlock()
// 如果已存在,先删除旧的
if item, exists := c.items[key]; exists {
c.usedSize -= int64(item.size)
delete(c.items, key)
}
// 检查是否需要清理空间
itemSize := len(data)
if int64(itemSize) > c.maxSize {
// 单个文件太大,不缓存
return
}
// 清理过期或最旧的项直到有足够空间
c.cleanup(int64(itemSize))
// 添加新项
c.items[key] = &CacheItem{
data: data,
timestamp: time.Now(),
size: itemSize,
}
c.usedSize += int64(itemSize)
}
// Remove 移除缓存项
func (c *ThumbnailCache) Remove(key string) {
c.mu.Lock()
defer c.mu.Unlock()
if item, exists := c.items[key]; exists {
c.usedSize -= int64(item.size)
delete(c.items, key)
}
}
// Clear 清空缓存
func (c *ThumbnailCache) Clear() {
c.mu.Lock()
defer c.mu.Unlock()
c.items = make(map[string]*CacheItem)
c.usedSize = 0
}
// cleanup 清理缓存,确保有足够空间
func (c *ThumbnailCache) cleanup(requiredSpace int64) {
// 首先清理过期项
now := time.Now()
for key, item := range c.items {
if now.Sub(item.timestamp) > c.ttl {
c.usedSize -= int64(item.size)
delete(c.items, key)
}
}
// 如果还不够,清理最旧的项
for c.usedSize+requiredSpace > c.maxSize && len(c.items) > 0 {
var oldestKey string
var oldestTime time.Time
for key, item := range c.items {
if oldestKey == "" || item.timestamp.Before(oldestTime) {
oldestKey = key
oldestTime = item.timestamp
}
}
if oldestKey != "" {
item := c.items[oldestKey]
c.usedSize -= int64(item.size)
delete(c.items, oldestKey)
}
}
}
// Size 获取缓存大小(字节)
func (c *ThumbnailCache) Size() int64 {
c.mu.RLock()
defer c.mu.RUnlock()
return c.usedSize
}
// Count 获取缓存项数量
func (c *ThumbnailCache) Count() int {
c.mu.RLock()
defer c.mu.RUnlock()
return len(c.items)
}
// Stats 获取缓存统计信息
func (c *ThumbnailCache) Stats() map[string]interface{} {
c.mu.RLock()
defer c.mu.RUnlock()
return map[string]interface{}{
"count": len(c.items),
"usedSize": c.usedSize,
"maxSize": c.maxSize,
"usagePercent": float64(c.usedSize) / float64(c.maxSize) * 100,
}
}