feat(external_systems): add graceful resource cleanup on app shutdown

新增外部系统模块的优雅关停逻辑,在应用关闭时释放所有连接池资源和适配器实例缓存,确保httpx、gRPC等连接能够正常发送FIN包完成关闭流程,而非依赖操作系统强制回收文件描述符。
This commit is contained in:
Kris 2026-06-25 16:56:19 +08:00
parent 9bdbc674b8
commit 23a0022d18
2 changed files with 39 additions and 0 deletions

View File

@ -12,6 +12,8 @@
from __future__ import annotations
from yuxi.utils import logger
def register_adapters() -> None:
"""显式注册所有外部系统适配器、认证插件与集成包。
@ -40,3 +42,28 @@ def register_adapters() -> None:
from yuxi.external_systems.integrations.discovery import discover_integration_packages
discover_integration_packages()
async def shutdown_external_systems() -> None:
"""应用关闭时释放外部系统模块持有的资源。
``register_adapters`` 对称 ``server/utils/lifespan.py`` 在应用关停时调用
释放顺序
1. ``pool_manager.close_all()``释放所有连接池句柄httpx/gRPC
2. ``default_registry.aclose_all()``释放适配器实例缓存资源
任一步失败仅记录日志不中断后续清理best-effort
"""
from yuxi.external_systems.framework.runtime.pool_manager import pool_manager
from yuxi.external_systems.framework.registry.adapter_registry import default_registry
try:
await pool_manager.close_all()
except Exception:
logger.warning("释放外部系统连接池失败", exc_info=True)
try:
await default_registry.aclose_all()
except Exception:
logger.warning("释放外部系统适配器实例失败", exc_info=True)

View File

@ -57,6 +57,18 @@ class PoolManagerImpl(PoolManagerPort):
for handle in pool.values():
await self._close_handle(handle)
async def close_all(self) -> None:
"""释放所有系统所有环境的连接资源。
应用关闭时由 ``shutdown_external_systems`` 调用确保 httpx/gRPC
连接句柄优雅关闭发送 FIN 而非依赖 OS 强制回收 FD
"""
async with self._lock:
for key in list(self._pools.keys()):
pool = self._pools.pop(key)
for handle in pool.values():
await self._close_handle(handle)
async def _close_handle(self, handle: Any) -> None:
"""关闭单个连接句柄(静默吞错)。"""
try: