Files
geMoldInsight/docs/archive/2026-09_governance_batches.md
cjw 79441a8a87 批次6:D4文档治理收口 + D13锁文件流程固化
D4 文档/规划/历史混放收口:
- docs/TECH_DEBT.md §2 由'按批次回顾'精简为'按主题摘要',
  与§3重复内容(批次0-4详细展开)整体迁入
  docs/archive/2026-09_governance_batches.md
- docs/STATUS.md 顶部 2026-09-17 之前条目迁入
  docs/archive/2026-09_status_history.md,仅保留指针
- D2 历史口径补齐为 2026-09-18 批次4后续专项清偿
- D4 标已清偿
- AGENTS.md / docs/archive/README.md 同步导航

D13 锁文件流程固化(镜像引入主体已清偿,仅剩锁文件落盘):
- 新增 deploy/generate_lockfiles.{sh,bat}:在 moldinsight conda
  环境(仅项目依赖)执行 pip freeze --exclude pythonocc-core,
  产出 deploy/requirements-{base,moldinsight}.lock.txt
- deploy/Dockerfile.moldinsight 注释改为指向生成脚本
- docs/OPERATIONS.md §2.1 增加完整流程说明
- tests/test_lockfile_generation.py 加锁文件存在性+体积契约;
  tests/conftest.py 注册 --run-lockfile-check 选项,
  默认 skip(仓库单测不阻塞),CI 镜像构建 job 显式启用 fail-fast

遗留:锁文件本身尚未落盘(本机Miniforge跨项目开发栈混装,
污染严重不能直接 pip freeze);待 CI / 生产首次构建时按流程落锁。

测试基线:126 passed, 9 skipped(默认4原有skip + D13新增5skip;
启用 --run-lockfile-check 时严格断言2项锁文件契约)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 09:59:02 +08:00

8.3 KiB
Raw Permalink Blame History

2026-09 后端设计治理批次实施流水账(归档)

文档定位:2026-09 设计审查产出的批次 0–4 与后续专项的完整实施流水账。 主骨架权威文档见:

批次 0(2026-09-16,安全与诚实)

  • /api/status/{task_id} 补 JWT 鉴权 + 任务归属校验(无 token 401 / 他人或无主任务 403 / 不存在 404)
  • 归属校验收敛为 TaskQueryService.ensure_task_access 供 task_router 与 advanced_router 共用(原 D5)
  • 上传预检 pythonocc_available 从硬编码 true 改为惰性真实探测
  • bcrypt 口令治理:创建侧超 72 字节显式拒绝、验证侧截断比较
  • SECRET_KEY 未配置 / RUSTFS_* 缺失时惰性校验抛明确错误
  • 完成态任务未持久化 analysis_metrics 时 /api/status 组装视图 500 修复
  • 测试基线:96 passed
  • 回归测试:tests/test_status_endpoint_auth.py 8 项
  • 接口行为变化已同步 ../API_CONTRACT.md §3.2

批次 1(2026-09-16,部署正确性)

  • 主处理链路改走 RustFS:分派入参 file_path → stp_file_id(原 D6)
  • 处理方按 PG 元数据从 RustFS 下载源文件到任务专属临时目录(保留原始文件名,下游产物命名不变),任务结束即清理
  • RustFS 不可用时回退 STPFile.file_path 节点本地路径;compose 为 backend / celery 增加共享卷 uploads_data / html_data 作过渡兜底
  • AUTO_MIGRATE 开关(settings / .env.example / compose 透传),默认 true 保持单机开发行为(原 D12)
  • 迁移目录 alembic/ → migrations/(修复 import alembic 命中本地目录遮蔽真实包的命名冲突)+ Docker 镜像补 COPY migrations/ + COPY alembic.ini
  • Dockerfile.moldinsight 改为 conda 运行时原生执行,基础镜像 tag 锁定(原 D13 主体)
  • compose 关键项去弱默认:SECRET_KEY / ADMIN_PASSWORD 改 ${VAR:?} 强制显式配置;create_admin_user 对空口令显式报错
  • 测试基线:98 passed, 1 skipped
  • 回归测试:tests/test_deployment_config.py

批次 2(2026-09-16,任务一致性模型)

  • Redis 进程内存回退彻底删除(写 no-op / 读 None,Redis 仅热缓存),PG 为任务状态单一事实源(原 D7)
  • 批量元数据入库:processing_tasks 新增 batch_id 列(迁移 a3f8c2d91e47),GET /api/batch/{batch_id} 改为 PG 聚合查询 + STPFile.user_id 归属校验
  • 删除 Redis batch key 与进程内 dict 双通道
  • TaskQueryService PG 视图与 batch 聚合响应补 progress / current_step
  • 型腔分模失败不再吞异常 → 任务 failed(原 D8)
  • 持久化事务边界收口:数据本体写方法只 flush,编排层分阶段原子收口(阶段 A 几何+网格、阶段 B 型腔+HTML+特征+指标+验证),失败先 rollback 再置 failed(原 D9)
  • 进度/状态更新保留即时 commit(长任务进度可见性)
  • 测试基线:105 passed, 1 skipped
  • 回归测试:tests/test_batch_status_pg.py 4 项 + tests/test_redis_no_fallback.py 3 项

批次 3(2026-09-17,API 与代码结构)

  • advanced_router 按职责拆为 design / cost / machining / export 四个子路由,端点路径不变(原 D1)
  • 全部请求体改 Pydantic 模型(request.json() 手动解析退役),校验失败统一 422
  • _get_cached_import 上提为 core_modules.py 共用
  • 路由装载失败显式化:ROUTE_MODULES 清单 + route_registry,失败经 /api/health 呈现 degraded(pythonocc 真实探测),DEBUG 下 fail fast
  • 纯 Python 重计算端点统一 asyncio.to_thread 投放线程池,不再阻塞事件循环
  • StorageIntegrationService(867 行)按职责拆为 TaskStorage / AnalysisStorage / FileHistory 三服务(原 D14 部分)
  • MAX_FILE_SIZE 接线生效、celery_app 复用 Settings.redis_url(原 D14 收尾)
  • 连带修复:管理员重置密码改 JSON body(原裸 str 参数被解析为 query param,前端发 body 必 422);Dockerfile.celery 的 FROM tag 与实际构建 tag 对齐
  • 接口变更三件套随批完成:openapi.json 重导出(76 paths)+ 前端 gen:api
  • 测试基线:122 passed, 2 skipped
  • 回归测试:4 个测试文件共 17 项(test_advanced_split_contract / test_route_load_status / test_config_governance / test_auth_password_reset)

批次 4(2026-09-17,架构演进)

  • 共享 ORM 按模块拆分(原 D3 主体):891 行 shared/models/database.py(31 模型类三类同居)拆为 shared/models/base.py(唯一 Base + 归属约定)/ shared/models/identity.py(7 表)/ moldinsight/models/(9 表)/ inventory/models/(catalog/warehouse/trading/finance 15 表)
  • 三条跨模块 ORM relationship(User.stp_files / STPFile.user / STPFile.product)经全仓核实均无使用方,直接删除;跨模块桥接收敛为裸 FK 硬规则(../ARCHITECTURE.md §5.1)
  • 约 45 处 import 全量改写,无兼容 facade
  • 全量注册点收敛为 migrations/env.py 与 tests/conftest.py
  • 零调用方的死方法 db_manager.create_tables 一并删除
  • _reset_occ_executor 补 cancel_futures=True(旧实现下"慢恢复"的旧线程会继续消化旧队列,与新 executor 并发操作非线程安全的 OCC,属数据竞争而非单纯泄漏,原 D10 短期治理)
  • 吞吐路线定稿于 topics/performance/OCC_THROUGHPUT.md(短期 A:celery prefork 伸缩 + max-tasks-per-child 兜底;中期 B:run_occ 接口进程化 + kill-on-timeout 根治)
  • 顺手清偿 D15:vite.config.ts 删除未用的 mode 参数,vue-tsc -b 恢复通过
  • 回归测试:tests/test_model_ownership.py(31 表全量注册 / 单模块独立 mapper 配置 / 旧模块无 facade)
  • 测试基线:125 passed, 2 skipped
  • 接口面零变化(无 openapi 重导出)

批次 4 后续专项(2026-09-18)

  • D11 清偿:可视化报告 RustFS 单源化
    • 写侧 HTMLGenerator 每任务写临时目录,.html/_summary.json/_data.json 三件统一裸传 RustFS 报告键 html/reports/{filename}
    • 读侧 /html StaticFiles 本地挂载删除,新增代理路由 html_report_router.py(报告键直取 → 遗留 html/{hash}.json JSON 包装解析 → 本地卷存量兜底 → 404)
    • 防路径穿越(单段文件名校验),URL 形状 /html/{filename} 不变
    • 部署:celery 服务摘除 html_data 卷;Dockerfile.moldinsight 删除 COPY html_output/
    • 已知约束:报告路由不做认证(iframe 无法携带 Authorization 头)
    • 删除 get_stp_file_with_data 的死数据块
  • OCC 方案 A 部署参数落地:CELERY_CONCURRENCY / CELERY_MAX_TASKS_PER_CHILD 进 Dockerfile.celery + compose + .env.example
  • D2 清偿:铝价响应带 source: "simulated";前端按来源渲染"模拟数据 · 参考走势"标注;死代码 getAluminumPrice 删除
  • D10 方案 B 实施:run_occ(fn, *args) → run_occ(op_name, payload);常驻 OCC 进程池 + kill-on-timeout 根治残留线程泄漏
  • CI 门禁:.gitea/workflows/ci.yml 三 job(pytest / 前端构建 / openapi 漂移检测)
  • 接口变更三件套随批完成:openapi.json 重导出(76→77 paths,新增 /html/{filename})+ 前端 gen:api 再生
  • 测试基线:143 passed, 0 skipped

后续小步治理(2026-09-21 ~ 2026-09-22)

  • 2026-09-21 inventory 业务层继续沉淀批次(4 批):
    • customer / supplier / warehouse → master_data_service
    • material_routes(价格历史 / 趋势 / 供应商关联)→ material_service
    • product_routes(CRUD / BOM / from-task 跨模块桥接)→ product_service
    • dashboard_routes(首页统计 / 低库存预警)→ dashboard_service
  • 2026-09-22 schema / datetime 现代化弃用清零(D12):
    • 全仓 14 处 class Config: + auth_routes 三处全部迁移到 model_config = ConfigDict(from_attributes=True)
    • auth_service.py 中 datetime.utcnow() 改用 datetime.now(timezone.utc)
  • 测试基线最终落点:126 passed, 4 skipped,零 deprecation warning