批次4后续专项完成:D11清偿 + OCC方案B实施 + 部署参数 + D2诚实标注 + CI门禁

① D11 HTML 报告 RustFS 单源化(TECH_DEBT P2 清偿):可视化产物写任务临时目录后
   裸传报告键 html/reports/{filename}(文件名寻址),/html StaticFiles 挂载删除,
   新增 html_report_router 根路径代理(报告键→遗留 JSON 包装→本地卷兜底→404,
   防穿越);URL 形状 /html/{filename} 不变,持久化引用零迁移;celery 摘除
   html_data 卷,镜像不再烤入陈旧报告;顺带删除 get_stp_file_with_data 死数据块
② OCC 方案 B(D10 清偿):run_occ(op_name, payload) 契约 + 常驻工作进程池
   (occ_process_pool + occ_worker 操作注册表),超时/崩溃 terminate 换新补位、
   任务级超时 recover 整体重建,残留线程泄漏根治;TopoDS 不跨进程(generate_cavity
   分模 + 方案 STEP 持久化全在子进程内,返回 export_manifest);删除内存形状缓存链、
   CADExporter.export_mold_results、shape_loader(→ stp_materializer)
③ OCC 方案 A 部署参数:CELERY_CONCURRENCY / CELERY_MAX_TASKS_PER_CHILD 进
   Dockerfile.celery + compose + .env.example
④ D2 诚实标注:铝价响应带 source: "simulated",前端按来源渲染标注(原硬编码
   "上海期货交易所"属虚假声明),死代码 getAluminumPrice 删除
⑤ CI 门禁:.gitea/workflows/ci.yml 三 job(pytest / 前端构建含 vue-tsc /
   openapi 漂移检测)

接口变更三件套随批完成(openapi 76→77 paths + gen:api + 前端构建通过;方案 B
接口面零变化)。测试基线 143 passed, 0 skipped(新增 16 项)。文档六处同步。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-09-18 17:22:01 +08:00
parent 0e6b3b1811
commit e728dcd226
36 changed files with 1474 additions and 565 deletions
+17 -13
View File
@@ -3,8 +3,8 @@
- 请求体一律 Pydantic 模型(原 request.json() 手动解析退役,校验失败统一 422)
- 纯 Python 设计计算统一经 asyncio.to_thread 投放线程池,不阻塞事件循环;
OCC 相关的倒扣检测仍走 processing_service.run_occ 的单线程 executor
(PythonOCC 非线程安全)
OCC 相关的倒扣检测经 processing_service.run_occ 的常驻 OCC 进程池
(PythonOCC 非线程安全,进程内串行;见 OCC_THROUGHPUT.md 方案 B)
"""
import asyncio
from typing import List, Optional
@@ -165,17 +165,21 @@ async def detect_undercuts(
if not sd:
raise HTTPException(503, "服务不可用:核心模块未加载")
# 从持久化 STP 原件重建几何(此前传 shape=None 会被兜底吞掉,永远返回"无倒扣")
from moldinsight.services.shape_loader import get_shape_loader
shape = await get_shape_loader().load_shape_for_task(db_session, body.task_id)
if shape is None:
# 方案 B:从持久化 STP 原件落盘,倒扣分析在常驻 OCC 子进程内完成(形状不跨进程)
from moldinsight.services.stp_materializer import get_stp_materializer
stp_path = await get_stp_materializer().materialize_stp_for_task(db_session, body.task_id)
if stp_path is None:
raise HTTPException(410, "任务几何不可用:无法从存储重建 STP 形状,请重新上传分析")
# OCC 操作必须走单线程 executor(PythonOCC 非线程安全)
result = await processing_service.run_occ(
sd.analyze_and_design,
shape,
body.parting_direction,
body.mold_size.model_dump(),
)
try:
result = await processing_service.run_occ(
"detect_undercuts",
{
"stp_path": str(stp_path),
"parting_direction": body.parting_direction,
"mold_size": body.mold_size.model_dump(),
},
)
finally:
stp_path.unlink(missing_ok=True)
return {"status": "success", "data": result}