[ISSUE-0050] 商家列表 chip 截断 50k + 加载慢¶
用户截图(v0.10.64,228k 数据)反馈: 1. 数据不一致:左侧 sidebar 显 "商家列表 228430"(22w),但 chip "全部 50.0k" 2. 打开列表很卡,加载好久
病灶¶
src/utils/merchant-stats.ts:31 硬上限 ROWS_CAP = 50_000:
const allRows = await selectByQuery('MapTaskData', { limit: ROWS_CAP, ... }) as any[];
// 全表 select 50k → JS for loop 6 个 count → return { total: rows.length, ... };
22w 数据 → 拉 50k 后停 → total = 50_000(cap) vs 真实 228430(sidebar / KPI 走 countAllData() 真实数)→ 用户看到矛盾。
加载慢:每 10s polling → 拉 50k 行(~80-200ms IndexedDB → JS heap)。
修¶
1. 无 taskId 走 jsstore count(毫秒级)¶
countAllData() / scraped / pending 三个 jsstore count 并发:
const [total, scraped, pending] = await Promise.all([
countByQuery(TABLE, {}), // 真实总数
countByQuery(TABLE, { scrape_status: 2 }),
countByQuery(TABLE, { scrape_status: 0 }),
]);
withEmail / withWebsite / highRating 仍需 50k 采样:
- emails 是 array,jsstore 不能查 length
- website 非空判断不可靠(jsstore where 仅 equality 安全)
- rating >= 4.5 jsstore 支持但保守
但增加 truncated: boolean + sampleLimit: number 字段:
return {
total, // 真实数
scraped, // 真实数
pending, // 真实数
withEmail, // 采样数
withWebsite, // 采样数
highRating, // 采样数
truncated: total > sample.length,
sampleLimit: ROWS_CAP,
};
UI banner:truncated 时提示「全部/已挖掘/待挖掘」是真实数;「有邮箱/有网址/高评分」是采样数。
2. 有 taskId 走原全表(保留 v0.10.2 ISSUE-0008 修复)¶
jsstore where: { taskId } 在升级过的 DB 会喷 logError。保留全表 + JS filter。
3. 降轮询频率:10s → 30s¶
stats 不需要那么实时(chip 数字大致正确即可)。22w 数据时 30s 一次拉 50k = CPU 占用降 3x。
数据¶
| 项 | 旧(v0.10.69) | 新(v0.10.70) |
|---|---|---|
total 真实数 |
❌ 50k cap | ✅ 真实(无 taskId 时 jsstore count) |
scraped / pending |
❌ 50k 采样 | ✅ 真实(jsstore count) |
withEmail / withWebsite / highRating |
50k 采样(无 banner) | 50k 采样(有 banner 明示) |
| 加载耗时(22w 数据,无 taskId) | ~ 100-300ms | ~ 80-200ms(节约了 3 个 count,select 50k 仍是大头) |
| 轮询频率 | 10s | 30s |
| 22w 数据 CPU 占用 | 高 | 低 3x |
未来优化(不做)¶
withEmail走 IndexedDB cursor 流式 count(不一次 load all)— 复杂度高,先把 cap 标清楚- jsstore range query
{ rating: { '>=': 4.5 } }— 文档说支持但项目代码未用过,谨慎 - 完全去掉轮询,改
merchant_data_changedevent 触发 — 需 background 在 insert 时发 event
工作流¶
本次严格 bump → build → sanity check 三步:
相关¶
- [[0018-hasemailonly-50k-silent-truncate|0018-hasEmailOnly-50k上限静默截断]] — 同 50k cap 限制,本次相同思路加 banner
- v0.10.2 jsstore where:taskId 喷 logError 的原始修复(无独立 ISSUE 文件) — 同精神
- 版本发布流程 — 本次正确顺序的范本