Files
geMoldInsight/docs/TECH_DEBT.md
T

299 lines
10 KiB
Markdown
Raw Normal View History

2026-09-01 18:05:18 +08:00
# geMoldInsight 技术债与治理计划(TECH_DEBT)
> 文档定位:**当前活跃技术债与治理计划的权威文档**。
> 本文回答“现在还有哪些重要债务、优先级如何、下一步怎么处理”;不负责维护当前实现状态,当前状态见 [STATUS.md](STATUS.md)。架构边界见 [ARCHITECTURE.md](ARCHITECTURE.md),未来路线见 [ROADMAP.md](ROADMAP.md)。
> 本文由归档文档 [archive/MOLDINSIGHT_TECH_DEBT_PLAN.md](archive/MOLDINSIGHT_TECH_DEBT_PLAN.md) 收敛整理而来,保留活跃债务与治理结论,弱化详细实施流水账。
---
## 1. 当前技术债概览
当前最主要的技术债集中在两个区域:
- **moldinsight API 与处理链路的结构收口**
- **文档 / 部署 / 历史语义与当前代码现状未完全一致**
已经完成的高优先级治理不再作为持续待办反复展开,当前重点聚焦在“还没完成、且值得继续推进”的部分。
---
## 2. 已完成的重要治理(摘要)
以下高价值治理已完成:
### 2.1 安全与权限
- debug/history 路由补鉴权
- 任务访问控制收紧
- 无主数据不再默认放行
### 2.2 静默失败与可用性
- `detect-undercuts` 改为基于真实 shape 分析
- OCC 超时后重建 executor,避免全队列永久堵死
- 后台任务统一分派,补强引用与并发控制
### 2.3 状态存储与缓存
- Redis 任务状态改为 Hash 字段级更新,兼容旧格式
- 完成态任务视图增加缓存
- 导出缓存与持久化链路收口,支持重启后再导出
### 2.4 架构与代码清理
- 删除旧单体入口与死代码
- 设置惰性配置校验,提升可测试性
- Generator 公共接口提取完成,补充契约测试
详细历史过程保留在原始技术债文档中,后续将转入归档。
---
## 3. 当前活跃技术债
### D1. `advanced_router` 过大,职责混杂
现状:
- 导出、估算、设计/分析相关接口仍混在同一个 router 中
- 请求体仍有较多手动解析逻辑
影响:
- 路由边界不清晰
- OpenAPI 可读性差
- 接口参数校验不统一
- 后续继续扩展时维护成本高
建议:
- 拆分为 export / design / cost 等子路由
- 高优先级请求体改为 Pydantic 模型
优先级:**P1**
### D2. 铝价模拟数据未显式标注来源
现状:
- 铝价服务返回的是模拟/参考数据,但接口层未明确表达
影响:
- 容易误导前端与业务使用者,把模拟数据理解为实时行情
建议:
- 响应增加 `source: "simulated"`
- 前端界面同步标注“模拟/参考数据”
优先级:**P2**
### D3. shared/platform 边界仍需继续收敛
现状:
- `shared` 同时承担平台基础能力与部分历史耦合职责
- 共享 ORM 与 app factory 仍是主要耦合点
影响:
- 模块边界认知成本较高
- 新增逻辑容易继续堆入 shared
建议:
- 继续从文档、目录语义、职责边界上推进收敛
- 在后续实际重构中优先避免把业务逻辑继续沉入 shared
优先级:**P2**
### D4. 文档现状 / 规划 / 历史混放
现状:
- 文档存在部署说明重叠、计划/总结/权威文档混放
- README 承担过多职责
影响:
- 新成员难以判断“哪篇才是当前有效说法”
- 状态、部署、规划容易发生漂移
建议:
- 建立 `STATUS / ARCHITECTURE / ROADMAP / DEPLOYMENT` 主骨架
- 历史材料迁入 `docs/archive/`
优先级:**P1**
2026-09-15 18:07:33 +08:00
### D5. `/api/status/{task_id}` 未鉴权(安全缺口)
现状:
- [src/moldinsight/api/task_router.py](../src/moldinsight/api/task_router.py) 的 `/api/status/{task_id}` 未挂 `get_current_active_user`,也无任务归属校验
- 匿名可枚举任务号拉取完整分析视图(几何 / 型腔方案 / LLM 报告 / 服务器本地路径)
影响:
- 与"任务访问控制已收紧"的既有结论矛盾;任务号可经批量/历史接口关联到真实用户
- 属确认的安全漏洞,应最先修复
建议:
- 补 `Depends(get_current_active_user)` 并复用 `_ensure_task_access` 归属校验
优先级:**P0**
### D6. 主处理链路依赖节点本地文件路径
现状:
- 上传保存到本地目录,任务处理直接 `load_step_file(Path(file_path))`([processing_service.py](../src/moldinsight/services/processing_service.py))
- docker-compose 中 backend 与 moldinsight-celery 为独立容器且无共享 volume,worker 读不到 API 节点写入的本地文件
影响:
- 双容器部署下主流程必然 `FileNotFoundError`;代码已有从 RustFS 重建几何的 [shape_loader.py](../src/moldinsight/services/shape_loader.py),主链路却未复用
建议:
- 分派入参由 `file_path` 改为 `stp_file_id`,worker 端按 `object_key` 从 RustFS 下载后解析
优先级:**P0**
### D7. Redis 降级为进程内 dict,多副本状态不一致
现状:
- Redis 不可用时任务状态 / 批量元数据 / 任务视图缓存静默降级到各进程内存([redis_task_manager.py](../src/shared/services/redis_task_manager.py) / [batch_router.py](../src/moldinsight/api/batch_router.py) / [task_query_service.py](../src/moldinsight/services/task_query_service.py))
影响:
- 多 worker + 多 API 副本下各进程内存互相不可见:同一任务在不同副本读到不同状态
建议:
- PG 作为单一事实源、Redis 仅热缓存;内存回退仅限单进程 DEBUG 模式
优先级:**P1**
### D8. 型腔生成失败被静默标记为 completed
现状:
- `_step_generate_cavity` 异常时置 `plan_result=None` 继续主流程,最终任务标记 completed([processing_service.py](../src/moldinsight/services/processing_service.py))
影响:
- 核心能力失败却对外呈现"成功","完成"状态可信度低
建议:
- 型腔失败 → 任务 failed,或显式 `completed_with_fallback` 并前端标注
优先级:**P1**
### D9. 持久化事务边界破碎
现状:
- [storage_integration_rustfs.py](../src/moldinsight/services/storage_integration_rustfs.py) 各方法内部自行 `session.commit()`,编排层上下文又 commit
- 型腔保存失败时几何/网格等前期数据已提交落库
影响:
- 失败后留下已提交的半成品数据,无对账补偿
建议:
- 各方法不再自提交,由编排层统一提交;明确 RustFS 与 PG 写入顺序
优先级:**P1**
### D10. OCC 全局单线程串行 + 超时重建泄漏线程
现状:
- 所有 OCC 操作经 `max_workers=1` executor 串行([processing_service.py](../src/moldinsight/services/processing_service.py)),celery 并发无法扩展 OCC 吞吐
- 超时重建 executor 每次泄漏 1 个线程,长期运行只涨不降
影响:
- 一个长耗时型腔生成阻塞全部几何处理;线程随故障累积
建议:
- 记录吞吐上限为已知约束;线程泄漏治理方案设计先行(见 [ROADMAP.md](ROADMAP.md) §3.1 批次 4)
优先级:**P2**
### D11. HTML 报告本地磁盘与 RustFS 双写双读
现状:
- 可视化 HTML/摘要同时写本地 `html_output/`(/html 静态挂载)与 RustFS
影响:
- 多副本下 /html 命中结果取决于负载均衡,跨副本文件不共享;同一份报告两套来源
建议:
- 统一 RustFS 为唯一来源,本地仅作按需缓存
优先级:**P2**
### D12. 应用启动时自动执行 alembic 迁移
现状:
- [init_db.py](../src/shared/database/init_db.py) 在 web 进程 startup 中执行 `alembic upgrade head`
影响:
- 多副本并发迁移有竞态,且迁移阻塞服务就绪
建议:
- 迁移移出 web 进程,作为独立部署步骤(`AUTO_MIGRATE` 开关)
优先级:**P1**
### D13. PythonOCC 镜像引入方式脆弱 + 依赖无版本锁
现状:
- [Dockerfile.moldinsight](../deploy/Dockerfile.moldinsight) 从 conda env 拷贝 site-packages 进 python:3.12-slim
- [requirements.txt](../requirements.txt) 全部为 `>=` 下限,无锁文件
影响:
- slim 缺 libstdc++/libgomp 等运行时库,跨发行版拷二进制纯靠运气;构建不可复现
建议:
- 基础镜像改用完整 conda 环境;依赖以 pip-compile 锁文件固化
优先级:**P2**
### D14. 配置漂移:弱默认 / 死配置 / 重复解析
现状:
- RUSTFS_* 带 `localhost:8080` / `your-secret-key` 弱默认;compose 给 SECRET_KEY / ADMIN_PASSWORD 弱默认
- MAX_FILE_SIZE 配置项未被使用([file_handler.py](../src/shared/utils/file_handler.py) 硬编码 50MB)
- [celery_app.py](../src/celery_app.py) 重新 load_dotenv 并手拼 REDIS URL,与 settings 两份实现
影响:
- 违背"关键项不兜底"硬约束;配置行为与文档不一致
建议:
- 去掉弱默认、对齐或删除死配置、celery_app 复用 settings
优先级:**P2**
2026-09-01 18:05:18 +08:00
---
## 4. 当前推荐治理顺序
2026-09-15 18:07:33 +08:00
> 注:2026-09-15 后端设计审查后,治理**执行顺序**以 [ROADMAP.md](ROADMAP.md) §3.1 批次计划为准(批次 0–4);D5–D14 的批次归属见该表。本节保留原有优先项作为补充说明。
2026-09-01 18:05:18 +08:00
### 第一优先级
1. `advanced_router` 拆分
2. 高优先级接口补 Pydantic 请求模型
3. 文档主骨架收口并减少重复说明
### 第二优先级
4. 铝价模拟数据来源显式化
5. 部署历史文档归档
6. shared/platform 语义继续收敛
---
## 5. 治理原则
### 5.1 先收口接口与边界,再做更大结构调整
当前最值得继续投入的,不是大规模目录重写,而是:
- 先把接口边界、文档边界、部署边界收清楚
- 再逐步推进 shared/platform 的后续调整
### 5.2 优先做“降低长期维护成本”的改动
优先处理:
- 重复逻辑
- 模糊边界
- 静态契约缺失
- 文档漂移风险
### 5.3 已解决问题不再长期占据主文档中心
已经完成且稳定的问题,只在本文保留摘要结论;详细实施流水账后续归档,不继续作为主文档主体。
---
## 6. 与相关文档的边界
- 当前项目状态:看 [STATUS.md](STATUS.md)
- 当前架构与模块边界:看 [ARCHITECTURE.md](ARCHITECTURE.md)
- 后续演进路线:看 [ROADMAP.md](ROADMAP.md)
- 部署主题入口:看 [DEPLOYMENT.md](DEPLOYMENT.md)
- 原始 moldinsight 细粒度债务记录:看 [archive/MOLDINSIGHT_TECH_DEBT_PLAN.md](archive/MOLDINSIGHT_TECH_DEBT_PLAN.md)