From 4017f2af73f4f85e732b53aa38d4e22c1b312609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=92=95=E8=B0=B7=E9=85=B1?= Date: Mon, 29 Sep 2025 21:22:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E9=9F=B3=E9=A2=91?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=BC=93=E5=AD=98=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/dependencies/database.py | 8 ++++++++ app/router/private/audio_proxy.py | 9 ++++++--- app/service/audio_proxy_service.py | 27 ++++++++++++++------------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/app/dependencies/database.py b/app/dependencies/database.py index 0eae622..b8f2230 100644 --- a/app/dependencies/database.py +++ b/app/dependencies/database.py @@ -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 diff --git a/app/router/private/audio_proxy.py b/app/router/private/audio_proxy.py index 2b412eb..a6892c6 100644 --- a/app/router/private/audio_proxy.py +++ b/app/router/private/audio_proxy.py @@ -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}") diff --git a/app/service/audio_proxy_service.py b/app/service/audio_proxy_service.py index 16343ea..0209997 100644 --- a/app/service/audio_proxy_service.py +++ b/app/service/audio_proxy_service.py @@ -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)