fix(test): wait for a PostgreSQL fixture slot while the queue moves (BUG-1254)
Independent Staging Quality Gate / validate (push) Successful in 14m10s
Independent Staging Quality Gate / publish (push) Successful in 4m3s

The slot wait was a fixed 5 minutes from the moment a file started queueing.
With 46 fixture files sharing 2 slots the queue outlasted that, so whichever
file came last failed the gate at random (runs 1742 and 1746). The deadline
now restarts whenever a slot changes hands; only 10 minutes with no slot
changing hands (a hung holder) fails. The 2-slot cap from BUG-281 stays.

Full suite 4967 / fail 24, identical to 171a3f25; tsc 0; lint 0 errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-10-06 23:21:48 +08:00
co-authored by Claude Opus 5.5
parent fe9d03a9b7
commit 52d14e8fef
4 changed files with 71 additions and 7 deletions
+4 -4
View File
@@ -16781,16 +16781,16 @@
## BUG-1254 | staging 门禁偶发红:数据库测试排队等 PostgreSQL 槽位超时
- 状态:investigating(已定位原因,未修)
- 状态:fixed-pending-verify(分支 `codex/postgres-fixture-queue-20261006`;需在门禁上连续通过才标 resolved)
- 首次发现 / 最近更新:2026-10-06 / 2026-10-06
- 来源:门禁 run 1746(`171a3f25`)「Frontend and database tests」红;同日 run 1742(`da226db1`)同一步红,随后同代码的 run 1743(`e62d0a32`)通过。
- 影响面:Gitea `backend-quality-gate.yml` 的 `npm test --prefix frontend`;`frontend/tests/helpers/postgres-fixture.ts`。与被测提交的改动无关时也会红,阻断部署。
- 现象:`not ok - corrective migration clears untrusted clocks and serializes concurrent fourth/fifth people`,原文 `timed out waiting for a PostgreSQL fixture slot (2 concurrent compose networks). Docker address pools cannot host one network per parallel test file.`,`ERR_TEST_FAILURE`。
- 触发条件:全量并行 `npm test` 时,使用 `startPostgresFixture()` 的测试文件(2026-10-06 共 46 个)同时排队抢 2 个槽位,每个文件最多等 `FIXTURE_SLOT_WAIT_MS` = 5 分钟;排在后面的文件等满 5 分钟即失败,谁失败取决于调度,所以同一代码时红时绿。
- 根因:BUG-281 为防 Docker 地址池耗尽把并发限到 2 个槽位,但等待上限是固定 5 分钟;数据库测试文件从当时约 20 个增长到 46 个,排队总时长已超过 5 分钟。属于 BUG-281 修复的容量假设失效,不是新代码引入。
- 修复:未做。候选(待决定):①等待上限改为「只要持槽进程还活着就继续等」或按排队文件数放大;②`run-tests.mjs` 把 `database-*` 等用 fixture 的文件拆到单独一轮串行跑(与 `test:db` 同口径),其余仍并行。不改 `.gitea/workflows/**`。
- 验证:本机无可用 Docker,未复现;依据为门禁日志原文与 `postgres-fixture.ts` 的槽位 / 等待常量。
- 防复发:待修复时补:fixture 数量增长不应让门禁变成随机红。
- 修复:产品要求根治(2026-10-06)。`postgres-fixture.ts` 的等待从「从开始排队起固定 5 分钟」改为「按进展续期」:每次轮询记录各槽位的持有者(`slot:pid`),持有者有变化(有人释放或接手)就把截止时间推到现在 + `FIXTURE_SLOT_STALL_MS`(10 分钟);只有连续 10 分钟没有任何槽位易手(持有者疑似卡死)才失败,报错写明这一点。槽位上限 2 不变(BUG-281 的地址池保护不动);不改 `.gitea/workflows/**`。曾考虑把数据库测试拆成单独串行一轮,未采用:改动面大、门禁更慢,且排队本身已由槽位串行化。
- 验证:本机无可用 Docker,未复现;依据为门禁日志原文与 `postgres-fixture.ts` 的槽位 / 等待常量。`postgres-fixture-contract.test.ts` 新增 1 条(续期纯函数三种情形 + 取槽循环每次轮询重算截止时间),4/4 通过;全量 4967 项 fail 24,与 `171a3f25` 名单逐条一致;tsc 0、lint 0 error。门禁上的实际效果待推送后看。
- 防复发:等待不再与 fixture 文件数量挂钩;契约测试禁止再出现固定等待常量 `FIXTURE_SLOT_WAIT_MS`。若门禁总时长逼近 validate 的 45 分钟上限,再考虑提高槽位数(先查地址池余量)。
- 相关记录:BUG-281(槽位上限的来源)、BUG-266(runner 资源回收)。
- 复发自:BUG-281(同一机制的容量问题以另一种形式出现)。
- 修复版本:—