2026-04-23 23:37:39 +08:00
|
|
|
|
from fastapi import APIRouter
|
2026-04-23 23:57:34 +08:00
|
|
|
|
import importlib
|
2026-04-23 23:37:39 +08:00
|
|
|
|
|
2026-08-31 18:01:34 +08:00
|
|
|
|
from shared.config.settings import settings
|
2026-05-29 18:10:08 +08:00
|
|
|
|
from shared.utils.logger import get_logger
|
2026-09-17 16:15:49 +08:00
|
|
|
|
from moldinsight.api.route_registry import route_load_status
|
2026-09-18 18:21:01 +08:00
|
|
|
|
from moldinsight.api.html_report_router import include_into as include_html_report
|
2026-04-23 23:57:34 +08:00
|
|
|
|
|
|
|
|
|
|
logger = get_logger(__name__)
|
2026-04-23 23:37:39 +08:00
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
2026-04-23 23:57:34 +08:00
|
|
|
|
|
2026-09-17 16:15:49 +08:00
|
|
|
|
# 业务路由装载清单:新增路由必须登记于此。
|
|
|
|
|
|
# 失败语义(原 _safe_include 仅 WARNING 跳过,进程带病启动不可感知):
|
|
|
|
|
|
# - 非 DEBUG:记录进 route_load_status["failed"],/api/health 呈现 degraded
|
|
|
|
|
|
# - DEBUG:直接抛错 fail fast——开发环境路由缺失必须当场暴露
|
|
|
|
|
|
ROUTE_MODULES = [
|
|
|
|
|
|
# (label, module_path, debug_only)
|
|
|
|
|
|
("健康检查", "moldinsight.api.health_router", False),
|
|
|
|
|
|
("上传", "moldinsight.api.upload_router", False),
|
|
|
|
|
|
("批量", "moldinsight.api.batch_router", False),
|
|
|
|
|
|
("任务", "moldinsight.api.task_router", False),
|
|
|
|
|
|
("历史", "moldinsight.api.history_router", False),
|
|
|
|
|
|
("CAM", "moldinsight.api.cam_router", False),
|
|
|
|
|
|
("设计", "moldinsight.api.design_router", False),
|
|
|
|
|
|
("成本", "moldinsight.api.cost_router", False),
|
|
|
|
|
|
("加工", "moldinsight.api.machining_router", False),
|
|
|
|
|
|
("导出", "moldinsight.api.export_router", False),
|
|
|
|
|
|
("铝价", "moldinsight.api.aluminum_price_routes", False),
|
|
|
|
|
|
# 调试端点会 dump 全量任务数据,仅 DEBUG 模式注册(双重防线:还需登录)
|
|
|
|
|
|
("调试", "moldinsight.api.debug_router", True),
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _safe_include(label: str, module_path: str, debug_only: bool = False):
|
|
|
|
|
|
if debug_only and not settings.DEBUG:
|
|
|
|
|
|
route_load_status["disabled"].append({"label": label, "module": module_path})
|
|
|
|
|
|
return
|
2026-04-23 23:57:34 +08:00
|
|
|
|
try:
|
|
|
|
|
|
module = importlib.import_module(module_path)
|
|
|
|
|
|
router_obj = getattr(module, "router", None)
|
|
|
|
|
|
if router_obj is None:
|
|
|
|
|
|
raise ValueError("未找到 router 对象")
|
|
|
|
|
|
router.include_router(router_obj)
|
2026-09-17 16:15:49 +08:00
|
|
|
|
route_load_status["loaded"].append({"label": label, "module": module_path})
|
2026-04-23 23:57:34 +08:00
|
|
|
|
logger.info(f"{label} 路由加载成功")
|
|
|
|
|
|
except Exception as exc:
|
2026-09-17 16:15:49 +08:00
|
|
|
|
route_load_status["failed"].append(
|
|
|
|
|
|
{"label": label, "module": module_path, "error": str(exc)}
|
|
|
|
|
|
)
|
|
|
|
|
|
logger.error(f"{label} 路由加载失败: {exc}")
|
|
|
|
|
|
if settings.DEBUG:
|
|
|
|
|
|
raise
|
2026-04-23 23:57:34 +08:00
|
|
|
|
|
2026-08-31 18:01:34 +08:00
|
|
|
|
|
2026-09-17 16:15:49 +08:00
|
|
|
|
for _label, _module_path, _debug_only in ROUTE_MODULES:
|
|
|
|
|
|
_safe_include(_label, _module_path, _debug_only)
|
2026-09-18 18:21:01 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register_moldinsight_routers(app):
|
|
|
|
|
|
"""注册 moldinsight 全部业务路由到 app(D3 收敛:入口侧单点调用)。
|
|
|
|
|
|
|
|
|
|
|
|
- /api 聚合路由:各子路由模块装载失败经 ROUTE_MODULES/route_load_status 呈现
|
|
|
|
|
|
(/api/health degraded,DEBUG fail-fast),见 _safe_include
|
|
|
|
|
|
- HTML 报告代理挂根路径 /html/{filename}(URL 形状与原 StaticFiles 一致),
|
|
|
|
|
|
失败同样登记 route_load_status(html_report_router.include_into)
|
|
|
|
|
|
"""
|
|
|
|
|
|
app.include_router(router, prefix="/api")
|
|
|
|
|
|
include_html_report(app)
|