Skip to content

test(research): 终态等待改为墙钟预算,避免慢环境下误报未收敛 - #157

Merged
helsome merged 1 commit into
helsome:mainfrom
wxrbyte:codex/fix-research-terminal-wait
Sep 22, 2026
Merged

helsome merged 1 commit into
helsome:mainfrom
wxrbyte:codex/fix-research-terminal-wait

Conversation

@wxrbyte

@wxrbyte wxrbyte commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Closes #156

复现

在干净 main7c9b550)上运行:

bun test packages/shared/src/research/service.test.ts --isolate

连跑 3 次,稳定出现失败(详见 issue #156):

次数 pass fail
1 4 3
2 5 2
3 5 2

失败项:ResearchService > runs a report end-to-end and persists itResearchService > lists runs newest-firstResearchService > plans from the strategy and persists strategyId onto the report,报错均为 error: run research-<uuid> did not reach a terminal status,耗时 709–769ms。

同一问题在 GitHub Actions 上也出现过:PR #138Full unit tests (advisory)(run 35678224696 / job 106589165526)结果为 1605 pass / 2 fail,两个失败项即 ResearchService > lists runs newest-firstResearchService > plans from the strategy and persists strategyId onto the report

根因

waitForTerminal()固定 100 次迭代表达等待预算:

for (let i = 0; i < 100; i += 1) {
  const run = await service.getRun(runId);
  ...
  await new Promise((resolve) => setTimeout(resolve, 5));
}

每次迭代的实际墙钟成本 = 一次 service.getRun()(回读磁盘上的 run 存储)+ setTimeout(5),实测约 7ms/次,因此 100 次只覆盖约 500–700ms。流水线在慢机器 / 满载 CI 上跑完需要 700ms 以上,于是健康的 run 尚未收敛预算就已耗尽,被抛成 did not reach a terminal status

这是等待窗口的表达方式问题(迭代次数 vs 墙钟时间),不是被测行为的问题——run 最终确实会收敛。

修复

  • waitForTerminal() 改为墙钟 deadline 驱动:TERMINAL_WAIT_MS = 5_000do { ... } while (Date.now() < deadline)
  • 新增回归用例 ResearchService > keeps polling past the old fixed 500ms budget when the pipeline is slow:包装 service.getRun,模拟一条 800ms 后才收敛的流水线,断言 waitForTerminal 仍返回 completed

回归用例在旧实现下确实失败(把循环改回固定 100 次后单独跑该用例):

(fail) ResearchService > keeps polling past the old fixed 500ms budget when the pipeline is slow [813.32ms]
error: run research-07b21330-... did not reach a terminal status
 0 pass / 1 fail

预期 / 实际

  • 预期:run 在合理时间内收敛时 waitForTerminal() 返回终态;测试只因行为不对而失败。
  • 实际(修复前):预算耗尽先于收敛,健康 run 被误判;修复后按墙钟等待,正常返回终态。

范围

packages/shared/src/research/service.test.tswaitForTerminal 辅助函数 + 1 条新增用例,+33 / −2)。无生产代码改动,无可见 UI 变化

验证

环境:Windows 11(本机),Bun 1.4.2,分支基于 origin/main 7c9b550

命令 结果
bun test packages/shared/src/research/service.test.ts --isolate 8 pass / 0 fail(修复前 4–5 pass / 2–3 fail)
bun test packages/shared/src/research --isolate 108 pass / 0 fail,14 files
bun run typecheck 5 个工作区全部 exit 0(core / i18n / shared / ui / electron)
git diff --check 无空白错误

基线说明:上述失败在干净 main7c9b550)上同样复现,属 main 既有问题,本 PR 不夹带其他修复;修复后 packages/shared 的 research 目录全绿。

ResearchService 测试里的 waitForTerminal 用固定 100 次 × 5ms 的轮询预算,
实际只有约 500–700ms 墙钟时间;而 run 本身需要落盘后再轮询回读,在慢机器或
满载 CI 上完整跑完所需时间会超过这个预算,于是健康的 run 被判定为
"did not reach a terminal status"。

- waitForTerminal 改为基于墙钟 deadline(TERMINAL_WAIT_MS = 5000ms)轮询
- 新增回归用例:模拟 800ms 后才收敛的流水线,旧实现必然超时失败

影响:消除 Full unit tests (advisory) 因该等待窗口过短产生的偶发红灯
(如 PR helsome#138 的 advisory 作业 106589165526,2 fail / 1605 pass)。
范围:仅测试辅助函数与新增用例,无生产代码改动。
@helsome
helsome merged commit 275f590 into helsome:main Sep 22, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Tests] ResearchService 终态等待预算过短,慢环境下健康 run 被误判为未收敛

2 participants