docs: 记录 stuck 误报根因与本批(3/4/5 项)交付汇总
- 清单:新增 P0 章节(stuck 误报机制 + 6 条用例 + 撞锁守卫), 并补本批交付汇总表(含 5c 凭据轮换仍须外部操作) - 记忆:stuck 误判 → 自动重启的完整机制与修法;E2E 与采集器撞锁
This commit is contained in:
1 parent
ecae6767f9
commit
83f1546074
2 files changed
+97
No files matched your search
@@ -497,3 +497,39 @@ shebang / .pth。**`--check` 可作启动自检或 CI 门禁。**
|
||||
### 新增可复用工具(本批)
|
||||
`relocate_bundle_venvs.py`(venv 自包含,check 可作 CI 门禁)、
|
||||
`verify_fulltext_equivalence.py`(全文检索 vs LIKE 等价性对照)。
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 第十批(23:00–23:30):`stuck` 误报导致采集器被反复自动重启(根因)
|
||||
|
||||
### 机制(「一天被判定异常停止 193 次」的根因)
|
||||
- `get_status()` 用「DB 最后写入 > **300s**」判 `stuck`
|
||||
- 非交易时段节能模式:间隔 30s → **3600s**,**期间刻意不写数据**
|
||||
→ 每个非交易小时约 55 分钟被误判
|
||||
- `AutoRecoveryManager.swift:166`:`if st.stuck == true { return .collectorStuck }`
|
||||
→ **触发自动重启采集器**
|
||||
- 实证:20:27 / 20:46 / 21:05 / 21:24 / 21:49 / 22:11 规律性停止
|
||||
|
||||
### 修法
|
||||
`stuck` 改看**心跳**(心跳线程每 60s 刷新、长休眠也活跃;Swift 免 spawn 探测本就
|
||||
读心跳,本次统一 CLI 路径)。回退阈值 **4200s**(> 节能上限 3600s + 余量)。
|
||||
**无写入时间可比时保守判不卡死**(空库/DB 异常不触发重启)。
|
||||
`last_write_time` 语义不变。
|
||||
顺带修:DB 返回 datetime 对象时 `str()` 带微秒 → `strptime` 抛
|
||||
`unconverted data remains`;新增 `_parse_ts()` 容错。
|
||||
新增 6 条用例,5 条旧契约用例同步更新。Scripts/bin 214 → **220**。
|
||||
|
||||
### 附带:E2E 用例与采集器撞锁
|
||||
`test_unified_writer_e2e` 真写 `news_unified` → `(1205, Lock wait timeout)`。
|
||||
它此前"通过"只因采集器当时停摆 13 小时,**修好采集后反而暴露**。
|
||||
已加守卫:采集器活跃时 skip 并说明。kuaixun 54s → **3.9s**。
|
||||
|
||||
### 本批交付(第 3/4/5 项)
|
||||
- 3a P1-11:**否决**(ngram 与 LIKE 不等价)
|
||||
- 3b P2-19:`NewsFlashService.swift` 1054→821 + 3 extension(编译验证)
|
||||
- 3c P2-20:client 建 venv + 38 测试 + **修 SQL 注入** + 登记 CI
|
||||
- 4:三表增量路径已验证(opt_daily 1049 万行 14s)
|
||||
- 5a/5b:venv 内联自包含(59M)+ 补打包 `common/`
|
||||
- 5c:凭据轮换须外部操作(Tushare 后台 / MySQL 口令 + 7 个 plist)
|
||||
**测试合计 1147 passed。**
|
||||
@@ -1023,3 +1023,64 @@ kuaixun 因可能依赖本机服务单列为非阻塞。
|
||||
`PythonProcessManager.swift`(842)、`DatabaseSetupGuideView.swift`(807) 等。
|
||||
这些文件承载数据采集与进程管理的核心逻辑,拆分需逐文件评估依赖并逐一编译验证,
|
||||
不适合批量机械处理。
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 新增 P0:`stuck` 误报导致采集器被反复自动重启(2026-09-19 23:20 修复)
|
||||
|
||||
### 机制(这是「一天被判定异常停止 193 次」的根因)
|
||||
`get_status()` 用「数据库最后写入距今 > **300s**」判定 `stuck`;
|
||||
而非交易时段采集器进入节能模式,采集间隔由 30s 退避到 **3600s**
|
||||
(日志 `[eco] 非交易时段,采集间隔 30s → 3600s`)、**期间刻意不写数据**
|
||||
→ 每个非交易小时里约 **55 分钟**被误判为卡死。
|
||||
|
||||
同时 `AutoRecoveryManager.swift:166`:
|
||||
```swift
|
||||
if st.stuck == true { return .collectorStuck }
|
||||
```
|
||||
即 `stuck` 被当作可恢复故障 → **自动重启采集器**。
|
||||
|
||||
实证时间线(今日 debug.log):20:27 / 20:46 / 21:05 / 21:24 / 21:49 / 22:11
|
||||
呈规律性停止,间隔与健康检查周期一致。
|
||||
|
||||
### 修法
|
||||
`stuck` 改由**心跳**判定(心跳线程每 60s 刷新、长休眠时也活跃;Swift 侧的免 spawn
|
||||
探测本就是读心跳的,本次把 CLI 路径与之统一):
|
||||
- 心跳新鲜(≤3×60s)→ 不卡死
|
||||
- 心跳过期/缺失 → 回退判定,阈值取 **4200s**(>节能上限 3600s + 余量)
|
||||
- **无写入时间可比时(空库 / DB 读取异常)保守判为不卡死** ——
|
||||
`stuck` 会触发自动重启,误判代价高于漏判
|
||||
- `last_write_time` 语义不变,仍如实反映数据写入
|
||||
|
||||
顺带修解析脆弱性:DB 返回 `datetime` 对象时 `str()` 带微秒,
|
||||
原 `strptime("%Y-%m-%d %H:%M:%S")` 抛 `unconverted data remains: .219352`;
|
||||
新增 `_parse_ts()` 容错。
|
||||
|
||||
### 验证
|
||||
新增 6 条用例(核心回归:**节能空闲 1 小时但心跳鲜活 → 不得判 stuck**,
|
||||
旧逻辑必判 true);5 条旧契约用例同步更新。部署位实测
|
||||
`{"stuck": false}` 而 `last_write_time` 仍为 26 分钟前 —— 语义正确。
|
||||
|
||||
### 附带:kuaixun E2E 与采集器撞锁
|
||||
`test_unified_writer_e2e` 真实写 `news_unified`,与在跑的采集器撞锁:
|
||||
`(1205, 'Lock wait timeout exceeded')`。它此前"通过"只因采集器当时停摆 13 小时 ——
|
||||
**修好采集后反而暴露**。已加守卫:采集器心跳活跃时 `pytest.skip` 并说明原因,
|
||||
而非任其随机失败。kuaixun 耗时 54s → **3.9s**。
|
||||
|
||||
---
|
||||
|
||||
## 本批(第 3/4/5 项)交付汇总
|
||||
|
||||
| 项 | 结果 |
|
||||
|---|---|
|
||||
| **3a** P1-11 搜索提速 | ✅ 已评估并**否决**(实测 ngram 与 LIKE 不等价,会静默丢结果) |
|
||||
| **3b** P2-19 超大文件拆分 | ✅ 首批:`NewsFlashService.swift` 1054→821 + 3 个 extension(编译验证) |
|
||||
| **3c** P2-20 client | ✅ 建 venv + 38 条测试 + **修复 SQL 注入** + 登记 CI |
|
||||
| **4** 三表参数接线 | ✅ 已验证增量路径正确(`opt_daily` 1049 万行 14s 完成增量) |
|
||||
| **5a** venv 软链接脆弱 | ✅ 已修:运行时内联(裁至 59M)+ 修 shebang/.pth,`--check` 可作门禁 |
|
||||
| **5b** 打包漏 `common/` | ✅ 已修(并更正:桌面后端不导入 `app/main.py`,**未**造成当前故障) |
|
||||
| **5c** 凭据轮换 | ⬜ **须外部操作**:Tushare token 需在 tushare.pro 后台重置;MySQL 口令轮换需同步改 env 文件 + 7 个 launchd plist,属运维窗口动作 |
|
||||
|
||||
**测试总量:1147 passed**(core 122 / client 38 / tushare 174 / akshare 183 /
|
||||
Scripts 220 / kuaixun 410)。
|
||||
Reference in new issue
Block a user