P1-1: AIService/AIHandler 真单例 + lifespan close httpx 连接池(修复连接泄漏)
This commit is contained in:
@@ -96,14 +96,21 @@ def get_shared_wecom_service():
|
|||||||
|
|
||||||
|
|
||||||
def get_shared_ai_handler():
|
def get_shared_ai_handler():
|
||||||
"""获取 AIHandler 共享实例。
|
"""获取 AIHandler 共享实例(v4.0 P1-1:真单例)。
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
AIHandler: AI 处理器实例
|
AIHandler: AI 处理器单例
|
||||||
"""
|
"""
|
||||||
|
global _shared_ai_handler
|
||||||
|
if _shared_ai_handler is None:
|
||||||
from app.services.ai_handler import AIHandler
|
from app.services.ai_handler import AIHandler
|
||||||
from app.services.ai_service import AIService
|
from app.services.ai_service import AIService
|
||||||
return AIHandler(ai_service=AIService())
|
_shared_ai_handler = AIHandler(ai_service=AIService())
|
||||||
|
return _shared_ai_handler
|
||||||
|
|
||||||
|
|
||||||
|
# v4.0 P1-1: AIHandler 模块级单例(修复每次新建导致的 httpx 连接池泄漏)
|
||||||
|
_shared_ai_handler = None
|
||||||
|
|
||||||
|
|
||||||
# FastAPI Depends 函数(用于路由依赖注入)
|
# FastAPI Depends 函数(用于路由依赖注入)
|
||||||
@@ -134,14 +141,12 @@ def dep_wecom_service():
|
|||||||
|
|
||||||
|
|
||||||
def dep_ai_handler():
|
def dep_ai_handler():
|
||||||
"""AIHandler 依赖注入。
|
"""AIHandler 依赖注入(v4.0 P1-1:复用同一单例)。
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
AIHandler: AI 处理器实例
|
AIHandler: AI 处理器单例
|
||||||
"""
|
"""
|
||||||
from app.services.ai_handler import AIHandler
|
return get_shared_ai_handler()
|
||||||
from app.services.ai_service import AIService
|
|
||||||
return AIHandler(ai_service=AIService())
|
|
||||||
|
|
||||||
|
|
||||||
def dep_wingman_service():
|
def dep_wingman_service():
|
||||||
@@ -188,14 +193,28 @@ async def init_shared_services():
|
|||||||
async def cleanup_shared_services():
|
async def cleanup_shared_services():
|
||||||
"""清理共享服务(应用关闭时调用)。
|
"""清理共享服务(应用关闭时调用)。
|
||||||
|
|
||||||
关闭 Redis 连接池。
|
关闭 Redis 连接池 + AIService httpx 连接池(v4.0 P1-1)。
|
||||||
"""
|
"""
|
||||||
global _redis_pool
|
global _redis_pool, _shared_ai_handler
|
||||||
if _redis_pool:
|
if _redis_pool:
|
||||||
await _redis_pool.close()
|
await _redis_pool.close()
|
||||||
_redis_pool = None
|
_redis_pool = None
|
||||||
logger.info("共享服务清理完成")
|
logger.info("共享服务清理完成")
|
||||||
|
|
||||||
|
# v4.0 P1-1: 关闭 AIService 的 2 个 httpx 连接池(修复 Unclosed client session)
|
||||||
|
if _shared_ai_handler is not None:
|
||||||
|
try:
|
||||||
|
ai_service = getattr(_shared_ai_handler, 'ai_service', None)
|
||||||
|
if ai_service:
|
||||||
|
for client_attr in ('_client', '_native_client'):
|
||||||
|
client = getattr(ai_service, client_attr, None)
|
||||||
|
if client and not client.is_closed:
|
||||||
|
await client.aclose()
|
||||||
|
logger.info("AIService httpx 连接池已关闭")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"AIService 连接池关闭异常: {e}")
|
||||||
|
_shared_ai_handler = None
|
||||||
|
|
||||||
|
|
||||||
# Token 黑名单 Key 前缀(与 auth.py 中保持一致)
|
# Token 黑名单 Key 前缀(与 auth.py 中保持一致)
|
||||||
TOKEN_BLACKLIST_PREFIX = "token:blacklist:"
|
TOKEN_BLACKLIST_PREFIX = "token:blacklist:"
|
||||||
|
|||||||
Reference in New Issue
Block a user