# ============================================================================= # 企微智能IT支持服务台 — FastAPI 依赖注入 & 共享服务管理 # ============================================================================= # 说明:集中管理 Redis、AIService、WecomService、AIHandler 等共享服务实例, # 解决原代码中多处手动创建/关闭服务导致的资源泄漏问题。 # # 提供: # 1. 应用级共享实例的初始化和清理(在 main.py 的 lifespan 中调用) # 2. FastAPI Depends 依赖注入函数(供 h5.py 等路由模块使用) # 3. 模块级访问函数(供 wecom_callback.py 等非 DI 场景使用) # # 资源管理原则: # - 共享实例在应用启动时创建一次,关闭时清理一次 # - 路由端点通过 Depends 获取共享实例,不再手动创建/关闭 # - httpx.AsyncClient 连接池由共享 AIService 和 WecomService 复用 # ============================================================================= import logging from typing import Optional import redis.asyncio as aioredis from fastapi import Depends from app.config import settings from app.services.ai_service import AIService from app.services.ai_handler import AIHandler from app.services.wecom_service import WecomService from app.services.wingman_service import WingmanService logger = logging.getLogger(__name__) # -------------------------------------------------------------------------- # 全局共享实例(由 init_shared_services / cleanup_shared_services 管理) # -------------------------------------------------------------------------- _redis_client: Optional[aioredis.Redis] = None _ai_service: Optional[AIService] = None _wecom_service: Optional[WecomService] = None _ai_handler: Optional[AIHandler] = None _wingman_service: Optional[WingmanService] = None # -------------------------------------------------------------------------- # 应用生命周期管理(在 main.py 的 lifespan 中调用) # -------------------------------------------------------------------------- async def init_shared_services() -> None: """初始化共享服务实例(在应用启动时调用)。 创建 Redis 客户端、AIService、WecomService、AIHandler 的全局共享实例。 所有实例在应用运行期间复用,避免每次请求重新创建导致资源泄漏。 如果 Redis 不可用,会记录警告但不阻塞启动(降级运行)。 """ global _redis_client, _ai_service, _wecom_service, _ai_handler, _wingman_service # 1. 初始化 Redis 客户端(可能不可用,容错处理) try: _redis_client = aioredis.from_url(settings.redis_url) await _redis_client.ping() logger.info("共享 Redis 客户端初始化成功") except Exception as e: logger.warning(f"共享 Redis 客户端初始化失败(降级运行): {e}") _redis_client = None # 2. 初始化 AI 服务(共享 httpx 连接池) _ai_service = AIService() logger.info("共享 AIService 初始化成功") # 3. 初始化企微服务(使用共享 Redis) _wecom_service = WecomService(_redis_client) logger.info("共享 WecomService 初始化成功") # 4. 初始化 AI 处理器(统一 AI 调用逻辑) _ai_handler = AIHandler(_ai_service) logger.info("共享 AIHandler 初始化成功") # 5. 初始化 Wingman 服务(坐席智能副驾驶,独立 Agent) _wingman_service = WingmanService() logger.info("共享 WingmanService 初始化成功") async def cleanup_shared_services() -> None: """清理共享服务实例(在应用关闭时调用)。 按照依赖关系逆序关闭:AIHandler → WecomService → AIService → Redis。 确保所有 httpx 连接池和 Redis 连接被正确释放。 """ global _redis_client, _ai_service, _wecom_service, _ai_handler, _wingman_service # AIHandler 无需关闭(无外部资源) _ai_handler = None if _wecom_service: try: await _wecom_service.close() except Exception as e: logger.warning(f"WecomService 关闭异常: {e}") _wecom_service = None if _ai_service: try: await _ai_service.close() except Exception as e: logger.warning(f"AIService 关闭异常: {e}") _ai_service = None if _wingman_service: try: await _wingman_service.close() except Exception as e: logger.warning(f"WingmanService 关闭异常: {e}") _wingman_service = None if _redis_client: try: await _redis_client.close() except Exception as e: logger.warning(f"Redis 客户端关闭异常: {e}") _redis_client = None logger.info("共享服务实例清理完成") # -------------------------------------------------------------------------- # 模块级访问函数(供 wecom_callback.py 等非 DI 场景使用) # -------------------------------------------------------------------------- def get_shared_redis() -> Optional[aioredis.Redis]: """获取共享 Redis 客户端(非 DI 方式)。 适用于无法使用 FastAPI Depends 的场景(如回调处理器)。 Returns: Optional[aioredis.Redis]: Redis 客户端实例,不可用时为 None """ return _redis_client def get_shared_ai_service() -> Optional[AIService]: """获取共享 AI 服务(非 DI 方式)。 Returns: Optional[AIService]: AI 服务实例,不可用时为 None """ return _ai_service def get_shared_wecom_service() -> Optional[WecomService]: """获取共享企微服务(非 DI 方式)。 Returns: Optional[WecomService]: 企微服务实例,不可用时为 None """ return _wecom_service def get_shared_ai_handler() -> Optional[AIHandler]: """获取共享 AI 处理器(非 DI 方式)。 Returns: Optional[AIHandler]: AI 处理器实例,不可用时为 None """ return _ai_handler def get_shared_wingman_service() -> Optional[WingmanService]: """获取共享 Wingman 服务(非 DI 方式)。 Returns: Optional[WingmanService]: Wingman 服务实例,不可用时为 None """ return _wingman_service # -------------------------------------------------------------------------- # FastAPI 依赖注入函数(供路由端点使用) # -------------------------------------------------------------------------- async def dep_redis() -> Optional[aioredis.Redis]: """获取共享 Redis 客户端(FastAPI 依赖注入)。 Redis 不可用时返回 None,调用方根据业务需要决定是否降级处理。 Returns: Optional[aioredis.Redis]: Redis 客户端实例 """ return _redis_client async def dep_ai_service() -> AIService: """获取共享 AI 服务(FastAPI 依赖注入)。 AI 服务不可用时抛出异常(AI 为核心功能,不可降级)。 Returns: AIService: AI 服务实例 Raises: RuntimeError: AI 服务未初始化 """ if _ai_service is None: raise RuntimeError("AI 服务未初始化,请检查应用启动日志") return _ai_service async def dep_wecom_service() -> WecomService: """获取共享企微服务(FastAPI 依赖注入)。 企微服务不可用时抛出异常(核心通信功能,不可降级)。 Returns: WecomService: 企微服务实例 Raises: RuntimeError: 企微服务未初始化 """ if _wecom_service is None: raise RuntimeError("企微服务未初始化,请检查应用启动日志") return _wecom_service async def dep_ai_handler() -> AIHandler: """获取共享 AI 处理器(FastAPI 依赖注入)。 AI 处理器不可用时抛出异常(核心功能,不可降级)。 Returns: AIHandler: AI 处理器实例 Raises: RuntimeError: AI 处理器未初始化 """ if _ai_handler is None: raise RuntimeError("AI 处理器未初始化,请检查应用启动日志") return _ai_handler async def dep_wingman_service() -> WingmanService: """获取共享 Wingman 服务(FastAPI 依赖注入)。 Wingman 服务不可用时抛出异常。 Returns: WingmanService: Wingman 服务实例 Raises: RuntimeError: Wingman 服务未初始化 """ if _wingman_service is None: raise RuntimeError("Wingman 服务未初始化,请检查应用启动日志") return _wingman_service