1. 清理测试文件中未使用的导入与冗余代码 2. 修复审计日志与批量操作的空值约束,统一填充"global"作为默认渠道 3. 调整批量消息撤回的响应语义,对齐其他端点的部分成功契约 4. 修复访问规则批量克隆的唯一约束问题,新增后缀自动处理逻辑 5. 替换anyio为asyncio并行调用,修正时间UTC导入路径 6. 优化前端外部系统概览页的刷新状态提示与缓存逻辑 7. 修复测试用例中的断言与请求方式问题,适配httpx删除请求特性 8. 重构后端路由的依赖注入,移除冗余的数据库会话依赖 9. 调整测试用例的权限校验逻辑,修正强制登出的权限判断 10. 修复语义分块测试的numpy依赖问题,清理冗余导入
147 lines
7.5 KiB
Python
147 lines
7.5 KiB
Python
"""外部系统限界上下文 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)
|