package event import ( "sync" "time" ) // SessionUserCache 会话-用户映射缓存,支持TTL过期 type SessionUserCache struct { mu sync.RWMutex cache map[string]cacheEntry ttl time.Duration stopChan chan struct{} } // cacheEntry 缓存条目 type cacheEntry struct { userID string expiresAt time.Time } // NewSessionUserCache 创建新的会话-用户缓存 func NewSessionUserCache(ttl time.Duration) *SessionUserCache { cache := &SessionUserCache{ cache: make(map[string]cacheEntry), ttl: ttl, stopChan: make(chan struct{}), } // 启动清理协程 go cache.cleanupWorker() return cache } // Set 设置会话-用户映射 func (c *SessionUserCache) Set(sessionID, userID string) { c.mu.Lock() defer c.mu.Unlock() c.cache[sessionID] = cacheEntry{ userID: userID, expiresAt: time.Now().Add(c.ttl), } } // Get 获取用户ID,如果不存在或已过期返回空字符串 func (c *SessionUserCache) Get(sessionID string) string { c.mu.RLock() entry, exists := c.cache[sessionID] c.mu.RUnlock() if !exists { return "" } // 检查是否过期 if time.Now().After(entry.expiresAt) { // 异步删除过期条目 go c.deleteIfExpired(sessionID) return "" } return entry.userID } // Delete 删除指定会话的缓存 func (c *SessionUserCache) Delete(sessionID string) { c.mu.Lock() defer c.mu.Unlock() delete(c.cache, sessionID) } // deleteIfExpired 检查并删除过期条目 func (c *SessionUserCache) deleteIfExpired(sessionID string) { c.mu.Lock() defer c.mu.Unlock() if entry, exists := c.cache[sessionID]; exists { if time.Now().After(entry.expiresAt) { delete(c.cache, sessionID) } } } // cleanupWorker 定期清理过期条目的工作协程 func (c *SessionUserCache) cleanupWorker() { ticker := time.NewTicker(c.ttl / 2) defer ticker.Stop() for { select { case <-ticker.C: c.cleanupExpired() case <-c.stopChan: return } } } // cleanupExpired 清理所有过期条目 func (c *SessionUserCache) cleanupExpired() { c.mu.Lock() defer c.mu.Unlock() now := time.Now() for sessionID, entry := range c.cache { if now.After(entry.expiresAt) { delete(c.cache, sessionID) } } } // Stop 停止缓存清理协程 func (c *SessionUserCache) Stop() { close(c.stopChan) }