feat(v2.3): 完成关系表写入闭环

This commit is contained in:
Script Generator
2026-07-03 13:28:59 +08:00
parent e9ff986bac
commit bba02775dc
17 changed files with 732 additions and 18 deletions

View File

@@ -252,3 +252,18 @@ The first V2.2 read layer is query-first and AppData-compatible. `V22QueryModule
- Xiaobao warning reads `xiaobao_risk_summaries` first, then maps the precomputed summary into the existing warning UI shape.
During the V2.2 compatibility window, writes still go through the existing AppData stores. The frontend consumes V2.2 relation-table results for render-heavy pages and falls back to AppData only when the V2.2 read is unavailable or empty.
## V2.3 AppData-to-Relational Write Sync Layer (2026-07-03)
V2.3 closes the first compatibility gap after V2.2: AppData remains the frontend write source, but successful `PUT /api/v1/data/:key` calls now trigger a backend relation-table sync.
`DataService` writes AppData with the existing optimistic-lock rules first. After the AppData write succeeds, it calls `AppDataV23SyncService.syncAfterAppDataPut(key)`. Sync failures are logged and do not fail the user save, because AppData is still the source of truth during this compatibility window and V2.2 read paths keep their AppData fallback.
`AppDataV23SyncService` reuses the V2.2 pure mapper, then writes only the table family affected by the changed AppData key:
- `requirements` is replaced by `product_id` scope.
- `version_plans`, `dev_tasks`, `test_cases`, and `bugs` are replaced by `version_id` scope.
- `work_activities`, `task_worklogs`, `overtime_records`, `xiaobao_risk_snapshots`, and `xiaobao_risk_insights` remain append-oriented with duplicate skipping.
- `xiaobao_risk_summaries` is refreshed from risk snapshots and marked `dirty=true` when plans, tasks, test cases, bugs, activities, worklogs, or overtime change.
The server also has lightweight observability for this phase: a global API timing interceptor logs slow HTTP requests, and `PrismaService` logs slow query events. Thresholds are controlled by `API_SLOW_REQUEST_MS` and `PRISMA_SLOW_QUERY_MS`.

View File

@@ -529,3 +529,17 @@
- `xiaobao_risk_summaries` 不分区,保持 `version_id` 单行汇总;历史趋势进入分区快照表。
**理由**:把分区键纳入主键和唯一约束是 PostgreSQL 分区表的结构性要求。提前做这件事,可以避免客户数据变大后再重塑主键和外键。固定 HASH 分区避免每个项目/版本单独建分区的维护负担RANGE 分区只用于天然追加、按时间维护的历史数据。
## 43. V2.3 AppData 写入后非阻塞同步关系表
**问题**V2.2 已经让版本详情、需求池、与我相关和小宝预警优先读取关系表,但前端保存仍然写 AppData。如果关系表不跟随 AppData 更新,快读路径会逐渐变旧,最后又回落到加载大 JSON 文档,无法解决几十万条需求/任务/用例后的卡顿风险。
**决策**
- AppData 继续作为兼容窗口内的写入事实源,`DataService.put()` 先完成乐观锁写入,再触发关系表同步。
- 同步服务独立为 `AppDataV23SyncService`,复用 V2.2 mapper不把一次性迁移服务改造成在线写入服务。
- 当前态表按分区键作用域替换:需求按 `product_id`,版本计划/开发任务/测试用例/BUG 按 `version_id`
- 追加型证据表继续 `createMany(skipDuplicates)`,不因当前 AppData 文档缺失而删除历史。
- 小宝摘要由快照刷新;计划/任务/用例/BUG/活动/工时/加班变更只标记摘要 `dirty=true`,等待下一次规则计算刷新完整内容。
- 同步失败只记录日志,不阻塞 AppData 保存。慢 API 和慢 Prisma 查询先通过日志监控,后续再接 Prometheus/Grafana。
**理由**:这是从 AppData 兼容写入平滑过渡到领域 CRUD 的中间层。用户保存不能因为派生关系表暂时失败而丢失业务数据同时关系表保持跟随更新后V2.2 快读路径才能真正承受大数据量。把同步服务独立出来,也能让后续领域 CRUD 逐步替换 AppData 时复用同一套映射和小宝 dirty 策略。

View File

@@ -1,12 +1,17 @@
# 开发路线图
## 当前阶段V2.2分区关系表与高频读取热路径
## 当前阶段V2.3 — 关系表写入与预计算闭环
V2.2 已完成第一批高频读取热路径分区关系表基础、AppData 迁移预演、V2.2 scoped read API以及版本详情、需求池、与我相关小宝预警的前端快读接入。业务写入仍保留现有 AppData store 兼容窗口,后续再逐步打开关系表写入和领域 CRUD
V2.3 在 V2.2 快读路径之后补上写入闭环:前端仍保留现有 AppData Store 写入形状,但 AppData 保存成功后会同步关系表、刷新/标脏小宝风险摘要,并记录慢 API 与慢 Prisma 查询。领域 CRUD 仍是后续阶段,当前重点是让版本详情、需求池、与我相关小宝预警在大数据量下持续命中关系表快读
### 已完成(按时间倒序)
**2026-07-03**
- V2.3 AppData write-side bridge added: successful `PUT /api/v1/data/:key` calls now trigger `AppDataV23SyncService` relation-table sync after optimistic-lock AppData writes.
- Relation sync reuses the V2.2 mapper and replaces current-state rows by partition scope: requirements by `product_id`, version plans/dev tasks/test cases/bugs by `version_id`.
- Append-only evidence tables continue to use duplicate-skipping inserts for work activities, worklogs, overtime, Xiaobao snapshots, and Xiaobao insights.
- Xiaobao summaries now refresh from risk snapshots and are marked `dirty=true` when version risk inputs change.
- Added lightweight observability: slow API request logging through a global Nest interceptor and slow Prisma query logging through query events.
- V2.2 partitioned domain schema foundation added: `requirements` uses HASH partitioning by `product_id`; `dev_tasks`, `test_cases`, and `bugs` use HASH partitioning by `version_id`.
- Partitioned table primary keys and business unique constraints now include partition keys, for example `(id, version_id)` and `(version_id, code)`.
- Xiaobao precompute storage foundation added: `xiaobao_risk_summaries` stores the current version risk, and `xiaobao_risk_snapshots` stores historical snapshots.