package fqapi import ( "context" "encoding/json" "fmt" "time" ) // audioProxyEntry 音频代理缓存条目(Redis 版) type audioProxyEntry struct { OriginalURL string `json:"original_url"` DeviceID string `json:"device_id"` Headers map[string]string `json:"headers"` } const ( redisCacheKeyPrefix = "fq:cache:" redisAudioKeyPrefix = "fq:audio:" // audioCacheTTL 音频代理缓存有效期(匹配 CDN 链接有效期) audioCacheTTL = 2 * time.Hour ) // redisGetCache 从 Redis 获取正文缓存 func redisGetCache(key string) string { val, err := redisCache.Get(context.Background(), redisCacheKeyPrefix+key).Result() if err != nil { return "" // miss 或错误都视为未命中 } var cacheData CacheData if err := json.Unmarshal([]byte(val), &cacheData); err != nil { cacheLogger.Error("解析Redis缓存数据失败: " + err.Error()) return "" } cacheLogger.Debug("Redis缓存命中: " + key) if time.Now().Unix() < int64(cacheData.Expi) { return cacheData.Data } return "" } // redisUpdateCache 写入 Redis 正文缓存(TTL 与过期时间一致) func redisUpdateCache(key string, value string, expi int) error { cacheData := CacheData{ Data: value, Expi: float64(time.Now().Unix() + int64(expi)), } jsonData, err := json.Marshal(cacheData) if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() return redisCache.Set(ctx, redisCacheKeyPrefix+key, jsonData, time.Duration(expi)*time.Second).Err() } // saveAudioProxyEntry 将音频代理信息存入 Redis func saveAudioProxyEntry(key string, entry *audioProxyEntry) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() jsonData, _ := json.Marshal(entry) if err := redisCache.Set(ctx, redisAudioKeyPrefix+key, jsonData, audioCacheTTL).Err(); err != nil { audioLogger.Error("保存音频缓存到Redis失败: " + err.Error()) } } // loadAudioProxyEntry 从 Redis 读取音频代理信息,未命中或过期返回错误 func loadAudioProxyEntry(key string) (*audioProxyEntry, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() val, err := redisCache.Get(ctx, redisAudioKeyPrefix+key).Result() if err != nil { return nil, fmt.Errorf("音频信息不存在或已过期,请重新调用 /audio 接口") } var entry audioProxyEntry if err := json.Unmarshal([]byte(val), &entry); err != nil { return nil, fmt.Errorf("解析音频缓存失败: %w", err) } return &entry, nil }