"""外部系统限界上下文 Router 聚合层与共享装配层。 本模块承担两个职责: 1. **共享装配层**:为各子 Router 提供请求级独立 session 的 UseCases / 轻量 service 装配依赖(``get_use_cases`` / ``get_dashboard_service`` / ``get_adapter_stats_service``)。子 Router 通过 ``Depends(get_use_cases)`` 注入已装配的 ``UseCases``,不再各自调用 ``create_use_cases_from_db(db)``。 2. **Router 聚合层**:将 23 个子 router 通过 include_router 注册,统一挂载到 /system/external-systems 前缀下。子 router 只需声明相对前缀(如 /systems、 /tools),根前缀 /system/external-systems 由本聚合 router 统一追加。 独立 session 设计说明(参照 channels 模块): external_systems 模块 **不复用** 鉴权依赖(``get_db``)持有的 ``AsyncSession``, 而是通过 ``pg_manager.get_async_session_context()`` 开启独立的请求级会话。原因: 鉴权阶段执行的 ``SELECT`` 会触发 SQLAlchemy 2.0 autobegin 语义开启隐式事务, 若复用同一 session,控制面 ``TransactionPort.begin()`` 会在已存在的事务上再次 ``begin()``,且异常路径下底层 asyncpg 连接会残留 "manually started transaction", 连接归还连接池后被下个请求复用时触发 ``cannot use Connection.transaction() in a manually started transaction``。 独立 session 使事务边界由 external_systems 应用层独占控制,与鉴权会话隔离, 避免事务状态互相污染。会话生命周期限制在本次请求内,请求结束自动 commit(无异常)或 rollback(有异常)后关闭。 """ from __future__ import annotations from fastapi import APIRouter from yuxi.external_systems.infrastructure.container import ( UseCases, create_adapter_stats_service_from_db, create_dashboard_service_from_db, create_use_cases_from_db, ) from yuxi.external_systems.use_cases.ports import ( AdapterStatsServicePort, DashboardServicePort, ) from yuxi.storage.postgres.manager import pg_manager async def get_use_cases() -> UseCases: """装配 external_systems UseCases 集合(请求级独立 session)。 通过 ``pg_manager.get_async_session_context()`` 开启独立请求级 session, 调用 ``create_use_cases_from_db(db)`` 装配完整 24-service ``UseCases`` 容器, yield 完成后自动关闭 session。不复用 ``get_db`` session 的原因见模块 docstring。 Yields: 已装配的 ``UseCases`` 实例。 """ async with pg_manager.get_async_session_context() as db: yield create_use_cases_from_db(db) async def get_dashboard_service() -> DashboardServicePort: """装配轻量级 DashboardService(请求级独立 session)。 Dashboard 是纯聚合查询,无需完整 UseCases 容器。使用 ``create_dashboard_service_from_db(db)`` 轻量工厂仅构造 ``DashboardService``(仅注入 Repositories),降低延迟与资源消耗。 不复用 ``get_db`` session 的原因见模块 docstring。 Yields: 已装配的 ``DashboardServicePort`` 实例。 """ async with pg_manager.get_async_session_context() as db: yield create_dashboard_service_from_db(db) async def get_adapter_stats_service() -> AdapterStatsServicePort: """装配轻量级 AdapterStatsService(请求级独立 session)。 AdapterStatsService 仅依赖 Repositories(纯查询用例,无副作用),无需 完整 UseCases 容器。使用 ``create_adapter_stats_service_from_db(db)`` 轻量工厂避免每次统计/健康查询都构造完整 24-service 容器。不复用 ``get_db`` session 的原因见模块 docstring。 Yields: 已装配的 ``AdapterStatsServicePort`` 实例。 """ async with pg_manager.get_async_session_context() as db: yield create_adapter_stats_service_from_db(db) external_systems_router = APIRouter( prefix="/system/external-systems", tags=["external-systems"], ) # 子 router 导入置于共享依赖定义之后,避免循环导入 # (子 router 通过 ``from server.routers.external_systems import get_use_cases`` # 反向引用本模块依赖,须保证此处已定义完成) from server.routers.external_systems.access_rule_router import access_rule_router # noqa: E402 from server.routers.external_systems.adapter_router import adapter_router # noqa: E402 from server.routers.external_systems.alert_router import alert_router # noqa: E402 from server.routers.external_systems.asset_router import asset_router # noqa: E402 from server.routers.external_systems.audit_log_router import audit_log_router # noqa: E402 from server.routers.external_systems.auth_plugin_router import auth_plugin_router # noqa: E402 from server.routers.external_systems.dashboard_router import dashboard_router # noqa: E402 from server.routers.external_systems.environment_router import environment_router # noqa: E402 from server.routers.external_systems.execution_router import execution_router # noqa: E402 from server.routers.external_systems.health_check_router import health_check_router # noqa: E402 from server.routers.external_systems.import_router import import_router # noqa: E402 from server.routers.external_systems.integration_router import integration_router # noqa: E402 from server.routers.external_systems.integration_tool_router import integration_tool_router # noqa: E402 from server.routers.external_systems.metric_router import metric_router # noqa: E402 from server.routers.external_systems.notification_channel_router import notification_channel_router # noqa: E402 from server.routers.external_systems.quota_router import quota_router # noqa: E402 from server.routers.external_systems.secret_rotation_router import secret_rotation_router # noqa: E402 from server.routers.external_systems.system_router import system_router # noqa: E402 from server.routers.external_systems.test_case_router import test_case_router # noqa: E402 from server.routers.external_systems.token_router import token_router # noqa: E402 from server.routers.external_systems.tool_router import tool_router # noqa: E402 from server.routers.external_systems.trash_router import trash_router # noqa: E402 from server.routers.external_systems.webhook_router import webhook_router # noqa: E402 # 注册 23 个子 router external_systems_router.include_router(system_router) external_systems_router.include_router(tool_router) external_systems_router.include_router(environment_router) external_systems_router.include_router(execution_router) external_systems_router.include_router(token_router) external_systems_router.include_router(audit_log_router) external_systems_router.include_router(asset_router) external_systems_router.include_router(adapter_router) external_systems_router.include_router(import_router) external_systems_router.include_router(integration_router) external_systems_router.include_router(integration_tool_router) external_systems_router.include_router(webhook_router) external_systems_router.include_router(health_check_router) external_systems_router.include_router(metric_router) external_systems_router.include_router(quota_router) external_systems_router.include_router(alert_router) external_systems_router.include_router(secret_rotation_router) external_systems_router.include_router(access_rule_router) external_systems_router.include_router(test_case_router) external_systems_router.include_router(dashboard_router) external_systems_router.include_router(auth_plugin_router) external_systems_router.include_router(notification_channel_router) external_systems_router.include_router(trash_router)