79441a8a87
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>
101 lines
8.3 KiB
Markdown
101 lines
8.3 KiB
Markdown
# 2026-09 后端设计治理批次实施流水账(归档)
|
||
|
||
> 文档定位:**2026-09 设计审查产出的批次 0–4 与后续专项的完整实施流水账**。
|
||
> 主骨架权威文档见:
|
||
> - [../STATUS.md](../STATUS.md)(每批次完成的时间点与产物)
|
||
> - [../TECH_DEBT.md](../TECH_DEBT.md)(活跃债务 / 已清偿项的当前位置)
|
||
> - [../ROADMAP.md](../ROADMAP.md)(批次计划与执行顺序)
|
||
> - [../ARCHITECTURE.md](../ARCHITECTURE.md)(平台 / 模块边界当前定稿)
|
||
|
||
## 批次 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](../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](../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
|