[ISSUE-0071] SPEC-006 cascade 删命中 ISSUE-0008 历史回归¶
agent code review 在 v0.10.86-102 改动中发现的 🔴 严重 #1。 v0.10.102 SPEC-006 实施时没查历史文档,直接
removeByQuery({taskId: id}),命中 v0.10.2 ISSUE-0008 的老 DB 升级坑。
病灶¶
坑的历史¶
v0.10.2 ISSUE-0008(无独立 ISSUE 文件,search-data.ts:67-91 注释 明确):
jsstore
where: { taskId }在升级过的 DB 上 — 即使 row.taskId 有值 — 也容易给 0 行。 早期 DB schema 没该列,jsstore 升级后 enableSearch 索引不完整。
v0.10.102 漏查 + 踩坑¶
SPEC-006 实施时 2 处用了不安全写法:
-
task-manager.ts:340removeByQuery: -
task-delete-confirm-dialog.tsx:77countByQuery:
用户可见后果¶
| 场景 | 表现 |
|---|---|
| 老用户(v0.10.0 之前升级过) | Dialog 显示"0 条商家数据" |
| 用户选"同时删 N 条" | 商家数据没删 → 孤儿 |
| 用户以为删干净 | 实际 TaskFilterPicker"已删任务"分组里还有 N 条 |
修(v0.10.103)¶
task-manager.ts — 改 select id 再 remove by id¶
if (payload?.deleteData === true) {
const allRows = await selectByQuery('MapTaskData', { limit: 200000 }) as any[];
const idsToDelete = allRows
.filter(r => r && r.taskId === id)
.map(r => r.id);
if (idsToDelete.length > 0) {
await removeByQuery('MapTaskData', { id: { in: idsToDelete } }); // ✅ id 主键安全
}
}
Dialog — 改 countAllByTaskIds¶
import { countAllByTaskIds } from '@/utils/jsstore/search-data';
const countMap = await countAllByTaskIds(200000); // ← search-data.ts 已有的安全 helper
const total = ids.reduce((sum, tid) => sum + (countMap[tid] || 0), 0);
附带优势:批量删 50 任务也只扫 1 次(之前串行 50 个 count,5s 卡顿 → 200-500ms)。
元教训¶
- CLAUDE.md 高频踩坑速查表里说"读源码顶部注释" — 我没读 search-data.ts 顶部就直接用 jsstore — 100% 踩坑路径
- 历史 ISSUE 没独立文件(v0.10.2 ISSUE-0008 只在注释里)→ 代码搜索难。所有踩坑应该写独立 ISSUE 文档 + audit_grep
- agent code review 必须做:本次纯靠自我审查会漏;agent 找到了
- SPEC 实施时:除了 SPEC 本身设计,应该 grep "相关字段"(taskId)所有历史使用,看是否有 anti-pattern 注释
audit_grep 防退化¶
audit_grep:
- pattern: "removeByQuery\\([^,]*MapTaskData[^,]*,\\s*\\{[^}]*taskId:"
description: "MapTaskData remove 不允许直接 where:taskId,必须先 select id + remove by id"
- pattern: "countByQuery\\([^,]*MapTaskData[^,]*,\\s*\\{[^}]*taskId:"
description: "MapTaskData count 不允许直接 where:taskId,必须用 countAllByTaskIds"
相关¶
- SPEC-006-task删除时商家数据二选一确认 — 引入 bug 的 SPEC
- search-data.ts:67-91 注释 — 历史病灶记录
- ISSUE-0008(无独立文件)— v0.10.2 jsstore where:taskId 喷 logError 的原始病灶