Skip to content

test(mojo): build 门禁里两条真 spawn 并发测试偶发失败,红起来与真回归同形 #1154

Description

@deepcoldy

问题

build job(CI 的必需检查,没有 continue-on-error 兜底)里有两条真 spawn worker 的重并发测试会偶发失败,一抖就挡住所有 PR:

  • test/mojo-cross-boundary.test.ts > 1. concurrently queued credential turns run A/B/C, not A/C/C
    AssertionError: expected [ '[A]', '[C]', '[C]' ] to deeply equal [ '[A]', '[B]', '[C]' ]
    
  • test/mojo-close-worker-journal.integration.test.ts > keeps writes fenced when recovery says retryable but admission says fenced

两条都是 13–16s 量级、bootWorker() 真起 worker 子进程 + IPC,断言依赖执行顺序而非确定性同步点。

证据

在 PR #1096 上观察到:同一个 SHA(78f673674,一字未改)两次 CI 结果相反 —— 第一次 build=failure(上面两条),重跑 build=success。⟹ 抖动,不是回归。

本地补充:

  • 单独跑 5/5 全绿;造并发负载(并行 6 个 vitest 进程后立刻跑)14/14 仍全绿 —— 本地压不出来,只在 CI runner 的真实调度抖动下触发
  • master 侧最近 8 个 build job 全 success 且这两条都过 ⟹ 概率上界大约 <1/8,但确实存在

为什么值得修

红起来与真回归完全同形。 #1096 里为了排除它,两个 reviewer 各花了一轮:先怀疑是新并进来的 #1057 动了 mojo spawn 时序(BOTMUX_REPLY_STYLE 注入落在 riff/mojo 的 env 分支上,看着很像),最后靠

git diff <before>..<after> -- src/worker.ts | grep -cE "applyMojoLivePatch|takeNormal|pendingMessages"   # => 0

证明 A/C/C 的守卫代码(worker.ts drain 循环里的 applyMojoLivePatch(item.mojoLivePatch))两侧逐字相同、且与 spawn 期 env 注入相位分离,才排除掉。这个排查成本本身就是稳定化的理由。

建议

  • mojo-cross-boundary 的 A/C/C:断言的是凭证 turn 排队顺序(修法本身在 drain 循环里、注释已说明 IPC-receive 时机会把 A/B/C 塌成 A/C/C)。建议加确定性同步点(等每个 turn 落地再发下一个的可观测信号),而不是靠 waitFor(lines >= 3) 后比较顺序
  • mojo-close-worker-journal:admission/recovery 竞态,同理
  • 若短期不便改造,至少把这两条从 build 门禁移到 advisory 腿,或标 retry —— 一个因环境而红的门禁会训练人忽略它(ci.yml 里 bun-test 的注释已经把这个道理写清楚了)

上下文

发现于 #1096 的评审收尾。该 PR 已合入(3b818ff69),本 issue 只记录这两条测试的稳定化,与 #1096 的改动无关。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions