docs: 记录第二批/第三批修复,并更正三处不准确表述
- 未解决问题清单:P1-8(门控 reroute)、P1-11(搜索 total)标记为已修; 修正编号混用;追加「本批更正」三章 - 复查报告:补充第二批 6 项闭环 + 两项新修的状态表,并说明两套 P1 编号的对应关系 - 记忆:记录根因、修法、证伪结果,以及三处自我更正与生产实测证据
This commit is contained in:
1 parent
f37e182a3b
commit
b2da02e40a
3 files changed
+116
-3
No files matched your search
@@ -99,3 +99,61 @@ CI 引用的 7 个路径现已全部在索引中;**CI 前三步本地实跑全
|
||||
**`grep` 的 `\|` 交替第六次咬人**:本次在 `grep -n "add_argument\|choices\|..."` 上再次返回空。
|
||||
已经在 MEMORY.md 记过四次,仍未改掉动作习惯。**唯一可靠做法:凡多模式,一律用 Grep 工具(ripgrep);
|
||||
写 Bash grep 时只允许单一 pattern。**
|
||||
|
||||
---
|
||||
|
||||
## 第三批(22:40–23:00):P1-8 门控死循环 + P1-11 搜索契约
|
||||
|
||||
### P1-8 Gate3→Gate2 reroute 不收敛 —— 根因是**职责契约矛盾**,不是级别配置
|
||||
- Gate2 的 docstring 明确写「OHLC 关系违反:**WARN(标记但不阻断)**」——这是设计意图;
|
||||
- Gate3 却把同一违规判为「Gate2 应该已检测但未阻断」并 `reroute_target="gate2_cleaning"`;
|
||||
- 回传一个**结论恒等、不改数据**的上游,数学上不可能收敛 → reroute 计数累加超
|
||||
`max_reroute` → `is_blocked=True` → **整批数据被丢弃不落库**。
|
||||
- 实测:3000 行中仅 1 行 `high < max(open,close)` 即触发,日志 `pipeline.step_reroute_limit count=4`。
|
||||
- **修法**:Gate3 不再为 OHLC 设 reroute(保留为 warn 级兜底记录);
|
||||
新增 `OHLC_SYSTEMIC_RATIO = 0.05`,仅当违规**占比**超阈值(整体损坏而非个别坏点)才 block ——
|
||||
block 是终态、不参与 reroute,故仍收敛。
|
||||
- **重要**:Gate3 是全仓**唯一**设置 `reroute_target` 的地方(用 ripgrep 确认)。
|
||||
修完后 reroute 机制在生产上已不可达(保留为公开 API 供未来 gate 使用)。
|
||||
|
||||
### ⚠️ 自我更正 1:原先"reroute 分支漏 pop"的说法不准确,该处**不是缺陷**
|
||||
实测双分支 DAG:`fetch_a`/`gate_a` 与 `fetch_b`/`gate_b`/`tail_b`,令 `gate_a` 上报 reroute 到 `gate_b`,
|
||||
结果 `fetch_a` 只执行 **1 次**。真实行为是「只有与 reroute 触发步骤**同批**完成的步骤会重复执行」,
|
||||
而对 reroute 目标的**下游**而言,重复执行正是"重置并重跑"语义所必需——强行补 `pop` 反而会破坏它。
|
||||
**代码未改**,报告已作废该表述。
|
||||
|
||||
### P1-11 搜索 total 契约
|
||||
- `total` 原为 `len(all_results)`,受 LIMIT 约束 → 恒等于 `min(limit,50)`。
|
||||
- 修法:新增与 data **完全同谓词**的 COUNT 查询;另加 `returned` 字段表示当页行数。
|
||||
- 实测:`q=股` 时 total=**63321**,与逐表 SQL 直查完全一致(cls 8577 / wallstreetcn 441 /
|
||||
sina 13341 / gelonghui 13431 / hotlist 18147 / 10jqka 9384)。修复前为 20。
|
||||
- 代价:`LIKE '%q%'` 无法走索引,多一次全表扫描;以正确性换一次扫描。FULLTEXT 提速仍未做。
|
||||
|
||||
### ⚠️ 自我更正 2:`ACTIVE_TABLES` 不含 `news_flash`
|
||||
`ACTIVE_TABLES = [news_cls, news_wallstreetcn, news_sina, news_gelonghui, news_hotlist, news_10jqka]`。
|
||||
原先用 `news_flash` 的 101,916 行去对比接口 total,是**拿两张不同的表在比**,口径错误。
|
||||
正确基准是 63,321。缺陷结论不变(20 vs 63321,差 3166 倍)。
|
||||
|
||||
### ⚠️ 自我更正 3:`external.py` 无同类问题
|
||||
其走 `dal.get_live_news()`,该函数本就实现了正确的 COUNT 模式(`subs, cnts`),返回真实 total。
|
||||
原报告称其"同构"属误判。
|
||||
|
||||
### 部署与验证
|
||||
- `gate.py` 与 `public.py` 已同步到部署位并实测:
|
||||
部署位代码 `blocked=False`;接口 `total=63321` 与 SQL 直查一致。
|
||||
- 回归:core 108 passed(+3)、kuaixun 407 passed(+2),5 条新用例**全部做过证伪**。
|
||||
- 提交:`81f6271`。
|
||||
|
||||
### 意外收获:v1.5.2 自动恢复已在生产实测通过
|
||||
臣从 shell 手动 `backend-start` 拉起的后端被工具回收(正是记忆里 `start_new_session` 那条),
|
||||
App 在 60s 健康检查内检测到并自动恢复,日志出现臣新增的计数文案:
|
||||
```
|
||||
[22:48:13] [ERROR] [NewsFlash] 后端服务异常停止
|
||||
[22:48:13] [INFO] [AutoRecovery] 自动恢复 快讯后端服务:进程异常退出(第 1 次尝试,近 60 分钟第 1 次故障)
|
||||
[22:48:34] [INFO] [AutoRecovery] 快讯后端服务 自动恢复成功
|
||||
```
|
||||
→ 新代码确实在生产运行,且熔断/告警计数按设计工作。
|
||||
|
||||
### 顺带:curl 访问本机服务被代理拦截
|
||||
`curl http://127.0.0.1:8100/...` 报 `upstream connect failed: Connection refused (os error 61)`,
|
||||
因会话代理未放行 127.0.0.1。**必须加 `--noproxy '*'`**。
|
||||
@@ -40,6 +40,31 @@
|
||||
|
||||
**未完成项**:P0-4(Pipeline 是否接入日更,需产品决策)、P0-5(凭据轮换需在 Tushare 后台操作)、P0-6(字段类型统一,涉及数据迁移)、P0-7 的正式入库、P1-1/P1-2(门控与管线,因 P0-4 未决而暂缓)、P1-5~P1-8、P2 全部。
|
||||
|
||||
### 第二批(09-18):6 项闭环 + 2 项新修
|
||||
|
||||
| 项 | 结果 |
|
||||
|---|---|
|
||||
| P0-1 部署 | ✅ **已部署 v1.5.2**(逐项核对新包修复标记 + 二进制符号;旧版留 597M 回滚点) |
|
||||
| P0-3 `dividend` 历史 | ✅ **19 行 → 216,364 行**。根因更深:`ann_date` 是**单日点查询而非区间**,该表结构上就装不下全量;改为按报告期 `end_date` 逐季分页幂等 upsert |
|
||||
| P0-5 凭据明文 | ✅ 移出 **7 个** plist(原报 5 个,已更正)→ `~/.config/findatahub/env`(0600),全部 LaunchAgent 明文归零 |
|
||||
| P0-7 版本控制 | ✅ 3 个提交;未跟踪 159→0、core 索引 0→45、App 74/74、CI 前三步实跑全通 |
|
||||
| P1-10 周/月线脱节 | ✅ 数据补齐(周线→20260911、月线→20260831)+ 银层迁移与分红刷新固化进 `tushare_sync.sh` |
|
||||
| P1-14 Swift 未编译 | ✅ `swift build --disable-sandbox` 通过并部署 |
|
||||
| **P1-1** 门控 reroute 不收敛 | ✅ **已修**:Gate3 不再为 OHLC 违规 reroute(回传恒等上游不可能收敛),改 warn;新增 `OHLC_SYSTEMIC_RATIO=0.05` 仅在系统性违规时 block。3 条证伪用例 |
|
||||
| **P1-6** 搜索 total 契约 | ✅ **已修**:total 取真实命中数(实测 63321 与 SQL 直查一致),新增 `returned` 字段。2 条证伪用例 |
|
||||
|
||||
> 编号说明:本节沿用**本复查报告**的 P1 编号(P1-1=门控 reroute、P1-6=搜索接口);
|
||||
> `FinDataHub-未解决问题清单` 用的是另一套序号(其 P1-8=门控 reroute、P1-11=搜索接口)。
|
||||
> 两处指同一组问题,以文件名区分。
|
||||
|
||||
**本批三处自我更正**(详见未解决问题清单末章):
|
||||
① 原称"reroute 分支漏 `pop` 致残留步骤重复执行"——实测不符,该处非缺陷,代码未改;
|
||||
② 原用 `news_flash` 统计做对比,而该表不在 `ACTIVE_TABLES` 内,口径错误(正确为 63,321 行;差 3,166 倍仍成立);
|
||||
③ 原称 `external.py` 与搜索接口"同构"——实测其走 `dal.get_live_news()`,本就返回真实 total,无缺陷。
|
||||
|
||||
**验证方式升级**:本批发现 `swift build` 的失败源于 SwiftPM 自身调用 `sandbox-exec`,
|
||||
`--disable-sandbox` 即可绕过——原先"只能做语法解析"的降级方案作废。
|
||||
|
||||
---
|
||||
|
||||
## 一、整体评估结论
|
||||
|
||||
@@ -23,11 +23,15 @@
|
||||
| P1-10 周/月线脱节 | ✅ **数据补齐**(周线 20260727→20260911、月线 20260731→20260831)+ 调度固化防复发 |
|
||||
| P1-14 Swift 未编译 | ✅ **`swift build --disable-sandbox` 通过**(SwiftPM 自身调 sandbox-exec 才是阻塞点) |
|
||||
|
||||
**2026-09-18 23:00 再更新**:P1-8(门控死循环)、P1-11(搜索 total 契约)已完成并部署验证,
|
||||
详见本节末「本批更正」与各自条目。
|
||||
|
||||
**仍未解决、且仍在造成影响的**:
|
||||
- **P0-6 `trade_date` 同列混存两种格式** —— 2026 年 60%(570,165 行)会被标准范围过滤静默丢弃
|
||||
- **P0-4 Pipeline/门控不在生产路径** —— 待产品决策,且阻塞 P1-8/P1-9 的排期
|
||||
- **P0-5 的凭据轮换**(外部动作)、`com.ths.dailyarchive` 需一次登录/重启才恢复加载
|
||||
- P1-8 门控死循环、P1-9 双源串源(均已可执行复现)、P1-11/12/13、P2 全部
|
||||
- P1-9 双源串源(形态需框架级改造,且其所在管线当前不可达 → 待 P0-4 决策)
|
||||
- P1-12 去重写连接、P1-13 句柄未关、P2 全部
|
||||
|
||||
**优先级总表**
|
||||
|
||||
@@ -40,10 +44,10 @@
|
||||
| **P0** | 5 | `trade_date` 同列混存两格式 + 跨库排序规则冲突 | ⬜ **未动(本轮最高剩余风险)** |
|
||||
| **P0** | 6 | 七步 Pipeline/四级门控不在生产路径 | ⬜ 待决策(阻塞 P1-8/P1-9) |
|
||||
| **P0** | 7 | 版本控制失效:核心库未入库、CI 必然失败 | ✅ 已完成(两个提交) |
|
||||
| P1 | 8 | Gate3→Gate2 reroute 不收敛,整批被阻断 | ⬜ 已可执行复现,待 P0-6 决策后排期 |
|
||||
| P1 | 8 | Gate3→Gate2 reroute 不收敛,整批被阻断 | ✅ **已修**(含 3 条证伪用例,已同步部署位) |
|
||||
| P1 | 9 | 双源并行共享 `context.df`,分支串源 | ⬜ 已可执行复现,同上 |
|
||||
| P1 | 10 | 清洗层周/月线脱节 + akshare 日更无告警 | ✅ 数据与调度已修;⬜ akshare 源侧落后 14 天的告警仍缺 |
|
||||
| P1 | 11 | 搜索 `total` 契约失真 + N 表 LIKE 全表扫描 | ⬜ 未动 |
|
||||
| P1 | 11 | 搜索 `total` 契约失真 | ✅ **已修**(total 真实命中数,实测 63321 与 SQL 直查一致);⬜ FULLTEXT 提速未做 |
|
||||
| P1 | 12 | 去重写入每条新建 4~5 个 MySQL 连接 | ⬜ 未动 |
|
||||
| P1 | 13 | 日志句柄与子进程流未关闭 | ⬜ 未动 |
|
||||
| P1 | 14 | Swift 改动未通过编译验证 | ✅ 已完成 |
|
||||
@@ -479,3 +483,29 @@ mysql -u root -h 127.0.0.1 -e "SELECT 'clean' 库, MIN(trade_date) 最早 FROM f
|
||||
|
||||
> 本文所有数字均来自本次实测(git 索引查询、MySQL 实库统计、运行中进程与日志、可执行复现脚本)。
|
||||
> 凭据类证据已脱敏,未记录明文值。
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 本批更正(臣自身两处表述不准,已在复核中证伪并更正)
|
||||
|
||||
### 更正 1:P1-8 的"附加缺陷"说法不准确
|
||||
原报告写"reroute 分支未 `remaining.pop(just_completed)` → 已完成步骤以 degree=0 残留、下一轮重复执行"。
|
||||
**实测不符**:构造双分支 DAG 探测(`fetch_a`/`gate_a` 与 `fetch_b`/`gate_b`/`tail_b`,
|
||||
令 `gate_a` 上报 reroute 到 `gate_b`),结果 `fetch_a` 只执行 **1** 次。
|
||||
真实行为是:**只有与 reroute 触发步骤同批完成的步骤会被重复执行**;而对 reroute 目标的
|
||||
下游而言,重复执行正是"重置并重跑"语义所必需 —— 若强行补 `pop` 反而会破坏它。
|
||||
结论:**该处不是缺陷,代码未改**。原表述已作废。
|
||||
|
||||
### 更正 2:P1-11 的对比口径错了
|
||||
原报告用 `news_flash` 表统计出"真实命中 99,359 行"与接口 `total=20` 对比。
|
||||
但 `ACTIVE_TABLES = [news_cls, news_wallstreetcn, news_sina, news_gelonghui, news_hotlist, news_10jqka]`
|
||||
**并不包含 `news_flash`**,所以那是拿两张不同的表在比。
|
||||
正确口径:6 张 ACTIVE_TABLES 同谓词合计 **63,321** 行(逐表:cls 8577 / wallstreetcn 441 /
|
||||
sina 13341 / gelonghui 13431 / hotlist 18147 / 10jqka 9384)。
|
||||
缺陷依然成立且严重(20 vs 63321,差 **3,166 倍**),但原始对比数字作废。
|
||||
|
||||
### 更正 3:`external.py` 无同类问题
|
||||
原报告称 `app/routers/external.py:42` 与搜索接口"同构"。实测其走的是
|
||||
`dal.get_live_news()`,该函数本就实现了正确的 `COUNT` 模式(`subs, cnts` 两套子查询),
|
||||
返回真实 `total`。**该处无缺陷**,属原报告误判。
|
||||
Reference in new issue
Block a user