fix:修复音频代理缓存报错

This commit is contained in:
咕谷酱
2025-09-29 21:22:06 +08:00
parent bc6553f143
commit 4017f2af73
3 changed files with 28 additions and 16 deletions

View File

@@ -39,6 +39,9 @@ engine = create_async_engine(
# Redis 连接
redis_client = redis.from_url(settings.redis_url, decode_responses=True)
# Redis 二进制数据连接 (不自动解码响应,用于存储音频等二进制数据)
redis_binary_client = redis.from_url(settings.redis_url, decode_responses=False)
# Redis 消息缓存连接 (db1) - 使用同步客户端在线程池中执行
redis_message_client = sync_redis.from_url(settings.redis_url, decode_responses=True, db=1)
@@ -82,6 +85,11 @@ def get_redis():
return redis_client
def get_redis_binary():
"""获取二进制数据专用的 Redis 客户端 (不自动解码响应)"""
return redis_binary_client
def get_redis_message():
"""获取消息专用的 Redis 客户端 (db1)"""
return redis_message_client

View File

@@ -7,7 +7,7 @@ from __future__ import annotations
from typing import Annotated
from app.dependencies.database import get_redis
from app.dependencies.database import get_redis, get_redis_binary
from app.service.audio_proxy_service import AudioProxyService, get_audio_proxy_service
from fastapi import APIRouter, Depends, HTTPException, Path
@@ -18,9 +18,12 @@ import redis.asyncio as redis
router = APIRouter(prefix="/audio", tags=["Audio Proxy"])
async def get_audio_proxy_dependency(redis_client: Annotated[redis.Redis, Depends(get_redis)]) -> AudioProxyService:
async def get_audio_proxy_dependency(
redis_binary_client: Annotated[redis.Redis, Depends(get_redis_binary)],
redis_text_client: Annotated[redis.Redis, Depends(get_redis)],
) -> AudioProxyService:
"""音频代理服务依赖注入"""
return get_audio_proxy_service(redis_client)
return get_audio_proxy_service(redis_binary_client, redis_text_client)
@router.get("/beatmapset/{beatmapset_id}")

View File

@@ -14,10 +14,11 @@ import redis.asyncio as redis
class AudioProxyService:
"""音频代理服务"""
def __init__(self, redis_client: redis.Redis):
self.redis = redis_client
def __init__(self, redis_binary_client: redis.Redis, redis_text_client: redis.Redis):
self.redis_binary = redis_binary_client
self.redis_text = redis_text_client
self.http_client = httpx.AsyncClient(timeout=30.0)
self._cache_ttl = 7 * 24 * 60 * 60 # 7天缓存
self._cache_ttl = 7 * 24 * 60 * 60
async def close(self):
"""关闭HTTP客户端"""
@@ -37,14 +38,14 @@ class AudioProxyService:
cache_key = self._get_beatmapset_cache_key(beatmapset_id)
metadata_key = self._get_beatmapset_metadata_key(beatmapset_id)
# 获取音频数据和元数据
audio_data = await self.redis.get(cache_key)
metadata = await self.redis.get(metadata_key)
# 获取音频数据(二进制)和元数据(文本)
audio_data = await self.redis_binary.get(cache_key)
metadata = await self.redis_text.get(metadata_key)
if audio_data and metadata:
logger.debug(f"Beatmapset audio cache hit for ID: {beatmapset_id}")
# metadata 格式为 "content_type"
return audio_data, metadata.decode()
# audio_data 已经是 bytes 类型metadata 是 str 类型
return audio_data, metadata
return None
except (redis.RedisError, redis.ConnectionError) as e:
logger.error(f"Error getting beatmapset audio from cache: {e}")
@@ -56,9 +57,9 @@ class AudioProxyService:
cache_key = self._get_beatmapset_cache_key(beatmapset_id)
metadata_key = self._get_beatmapset_metadata_key(beatmapset_id)
# 缓存音频数据和元数据
await self.redis.setex(cache_key, self._cache_ttl, audio_data)
await self.redis.setex(metadata_key, self._cache_ttl, content_type)
# 缓存音频数据(二进制)和元数据(文本)
await self.redis_binary.setex(cache_key, self._cache_ttl, audio_data)
await self.redis_text.setex(metadata_key, self._cache_ttl, content_type)
logger.debug(f"Cached beatmapset audio for ID: {beatmapset_id}, size: {len(audio_data)} bytes")
except (redis.RedisError, redis.ConnectionError) as e:
@@ -122,7 +123,7 @@ class AudioProxyService:
return audio_data, content_type
def get_audio_proxy_service(redis_client: redis.Redis) -> AudioProxyService:
def get_audio_proxy_service(redis_binary_client: redis.Redis, redis_text_client: redis.Redis) -> AudioProxyService:
"""获取音频代理服务实例"""
# 每次创建新实例,避免全局状态
return AudioProxyService(redis_client)
return AudioProxyService(redis_binary_client, redis_text_client)