背景
- HEAD 长期停在 08-03 的安全审计提交,此后六周的工作全部只在工作区。
- 更严重的是部分源码从未进入过版本控制(非"改了没提交"):
· Services/findatahub-core/ 索引 0 条 —— 18 个核心模块(pipeline/gate/cleaner/
db/cross_validator/health/retry…)全新 clone 拿不到
· Services/findatahub-client/ 索引 0 条
· App/Sources 磁盘 74 个 .swift、索引 54 —— 20 个未入库(AutoRecoveryManager、
全套 Settings*Section、PowerSaver、MySQLOnDemandManager、DependencyScanner…)
一次 `git clean -fd`、误删目录或磁盘故障即可不可恢复地丢失这些文件。
本提交内容
1. 补齐上述未跟踪源码、测试、文档与报告(Services/App/Docs/Tests/根报告)。
2. 纳入 .workbuddy/memory(项目知识)与 .github CI 配置。
3. 本次代码与架构复查的修复(详见下一段说明):
- Scripts/bin/common.py PidManager.status 改 split(":", 1),修复时间戳被截断到整点
- Scripts/bin/db_pool.py 取连接加超时、归还前 rollback、失败归还池位、双检锁初始化
- Scripts/bin/newsflash_backend.py _query_all 改 try/finally 无条件归还连接
- Scripts/bin/newsflash_collect.py 新增 _install_crash_handlers(faulthandler + excepthook)
- tushare_fetcher/core/fetcher.py _fetch_static 增量走 upsert,仅全量快照才 replace
- tushare_fetcher/scripts/tushare_sync.sh 银层迁移补 stock_weekly/stock_monthly;
月度增加分红按报告期全量刷新
- kuaixun-service/extend/content_enricher.py 禁用自动重定向 + 逐跳 SSRF 校验
- App/.../AutoRecoveryManager.swift 反复故障改告警不熔断(避免拉长数据空窗)
- 新增 Scripts/bin/repair_dividend_history.py(分红历史修复,按报告期分页幂等 upsert)
- 新增 Docs/repro/*(两个可运行的缺陷复现脚本)
- 补齐 6 个文件共 20 条回归用例(均做过证伪:旧实现下必然失败)
安全
- 已确认未纳入任何凭据:Services/tushare_fetcher/.env 被其 .gitignore 覆盖;
~/.config/findatahub/env(0600)在仓库外。
验证
- Python 测试 1074 passed(Scripts/bin 207 / core 105 / tushare 174 / kuaixun 405 / akshare 183)
- Swift 经 `swift build --disable-sandbox` 编译通过,产物 v1.5.2 已部署
3.5 KiB
测试缺口分析报告
运行时间: 2026-08-09 22:00
审查范围: 最近 7 天 git 提交 (bace1b9 ~ 4b62693)
涉及模块: akshare_fetcher, tushare_fetcher, newsflash_collect, sync_bridge, check_db, init_db
一、新增测试
1. test_newsflash_collect.py::test_db_error_stdout_clean
文件: Scripts/bin/tests/test_newsflash_collect.py
覆盖的风险行为: get_status() 在 DB 连接失败时将警告输出到 stdout,污染 JSON 导致 Swift 端 JSONDecoder 解析失败、误判 running: false,健康监控周期性误报"采集器异常停止"并反复启动采集器。
为何能降低回归风险: 原有测试 test_db_error_outputs_stderr 仅验证 stderr 有警告输出,但未验证 stdout 保持纯净。此测试直接断言 stdout 不包含任何警告文本("状态检查" / "失败" / "⚠️"),且 stdout 应为空字符串。如果未来有人误将 file=sys.stderr 改回 print()(默认 stdout),此测试会立即失败。
2. test_db.py(akshare)::TestEnsureMarketTableContract::test_database_manager_has_ensure_market_table
文件: Services/akshare_fetcher/tests/unit/test_db.py
覆盖的风险行为: fetcher.py:796 调用 self._db.ensure_market_table(table) 进行表结构迁移(补列、去重、补唯一索引),该方法通过继承 BaseDatabaseManager 提供。若未来重构移除该方法,sync_all_stocks() 会抛出 AttributeError,导致周线/月线同步完全不可用。
为何能降低回归风险: 这是一个接口契约测试,验证 DatabaseManager 类始终提供 ensure_market_table 方法。所有现有 ensure_market_table 测试使用 FakeDB mock,不会检测到真实类是否缺失方法。此契约测试填补了 mock 与真实实现之间的验证空白。
二、测试验证结果
| 测试套件 | 结果 |
|---|---|
| akshare test_db.py + test_fetcher.py | 101 passed, 4 skipped |
| Scripts/bin (newsflash_collect + sync_bridge + check_db + init_db) | 55 passed |
| tushare test_db.py + test_api.py | 53 passed, 5 failed (预存) |
预存失败(非本次引入)
tushare TestUpdateTableMeta(4个):db_mod.pymysql属性不存在 — 重构为BaseDatabaseManager后pymysql在基类导入,测试 monkeypatch 目标过时tushare TestThrottle::test_sleeps_when_within_interval: 时序断言0.3 < 0.3边界问题
三、覆盖良好的区域(本次无需补充)
| 区域 | 测试数 | 说明 |
|---|---|---|
_aggregate_ohlcv 周/月线聚合 |
12 | 覆盖基本聚合、trade_date 取值、单日边界、跨月周、vol/amount 求和、空 DataFrame、无 vol 列、非法 period |
max_stocks 调试截断 |
3 | 截断、零不截断、超额不截断 |
sync_cache 更新逻辑 |
3 | 全量同步标记、limit 模式不标记、无 cache 不崩溃 |
_pump_stream 流转发 |
6 | 多块转发、空 fd、OSError 退出、大块、逐块 flush |
tushare api.py 频率限流 |
4 | 分钟级 60s、泛化限流 60s、小时级 3665s、无时间单位 3665s |
tushare db.py update_table_meta |
3 | 有 date 列正常路径、无 date 列静态表路径、异常静默 |
| check_db 三库支持 | 5 | tushare 存在/不存在/三库全查、ready 判定、连接错误降级 |
| init_db tushare_data 初始化 | 7 | 建库建表、select_db、列结构、主键、execute_sql、check_database、main 集成 |
| newsflash_collect get_status | 12 | 未运行/运行中/卡住判定/DB 异常/时区解析/边界值/stdout 纯净性 |