flaky: enrollment.service.spec.ts asserts a 100ms wall-clock budget (missed by 6ms on CI) #1090

Closed
opened 2026-08-07 00:26:41 +00:00 by Mos · 0 comments
Contributor

Symptom

apps/gateway test step fails intermittently:

FAIL src/federation/__tests__/enrollment.service.spec.ts > EnrollmentService.create...
AssertionError: expected 900106 to be less than or equal to 900100
 ❯ src/federation/__tests__/enrollment.service.spec.ts:249:32

Cause

enrollment.service.spec.ts:249 asserts a wall-clock delta against a fixed 100 ms budget:

const before = Date.now();
// ... await create({ ttlSeconds: 9999 })
const expiresMs = new Date(result.expiresAt).getTime();
expect(expiresMs - before).toBeLessThanOrEqual(900_000 + 100);

The measured value was 900106 — the assertion missed by 6 ms. The budget covers everything between Date.now() and the service computing expiresAt, so on a loaded CI agent (this pipeline runs the test step alongside a Postgres service container and several other workspaces) a 100 ms allowance is not reliable.

This is a timing tolerance, not a correctness failure: the service is capping TTL at 900s exactly as intended, and the companion assertion expect(expiresMs - after).toBeGreaterThanOrEqual(0) passed.

Observed on

Pipeline 2258 (refs/pull/1085/head, commit 4b8c497e), step test, exit 1.

PR #1085 changes only .woodpecker/ci.yml, packages/mosaic/framework/tools/git/issue-close.sh, and its regression test — no overlap with apps/gateway. The same commit's test passes locally and inside the canonical ci-base:latest image.

Why this is filed rather than re-run

A green re-run would establish intermittency, not health. The race is still there; a pass is one sample from a distribution that also contains this failure. Re-rolling until green and calling it fixed is the shape this repo has been avoiding (cf. #3134 for the field-agent teardown race).

Suggested fix

Assert the invariant rather than the wall clock — e.g. inject a clock, or compare expiresAt against a captured timestamp with a tolerance sized to CI scheduling jitter (seconds, not 100 ms). Bumping the constant alone converts a sharp flake into a rare one.

Not measured

How often this recurs, and whether other wall-clock assertions in the same suite share the pattern. I have not swept for them.

## Symptom `apps/gateway` test step fails intermittently: ``` FAIL src/federation/__tests__/enrollment.service.spec.ts > EnrollmentService.create... AssertionError: expected 900106 to be less than or equal to 900100 ❯ src/federation/__tests__/enrollment.service.spec.ts:249:32 ``` ## Cause `enrollment.service.spec.ts:249` asserts a wall-clock delta against a fixed 100 ms budget: ```ts const before = Date.now(); // ... await create({ ttlSeconds: 9999 }) const expiresMs = new Date(result.expiresAt).getTime(); expect(expiresMs - before).toBeLessThanOrEqual(900_000 + 100); ``` The measured value was **900106** — the assertion missed by **6 ms**. The budget covers everything between `Date.now()` and the service computing `expiresAt`, so on a loaded CI agent (this pipeline runs the test step alongside a Postgres service container and several other workspaces) a 100 ms allowance is not reliable. This is a **timing tolerance**, not a correctness failure: the service is capping TTL at 900s exactly as intended, and the companion assertion `expect(expiresMs - after).toBeGreaterThanOrEqual(0)` passed. ## Observed on Pipeline **2258** (`refs/pull/1085/head`, commit `4b8c497e`), step `test`, exit 1. PR #1085 changes only `.woodpecker/ci.yml`, `packages/mosaic/framework/tools/git/issue-close.sh`, and its regression test — **no overlap with `apps/gateway`**. The same commit's test passes locally and inside the canonical `ci-base:latest` image. ## Why this is filed rather than re-run A green re-run would establish **intermittency, not health**. The race is still there; a pass is one sample from a distribution that also contains this failure. Re-rolling until green and calling it fixed is the shape this repo has been avoiding (cf. #3134 for the field-agent teardown race). ## Suggested fix Assert the invariant rather than the wall clock — e.g. inject a clock, or compare `expiresAt` against a captured timestamp with a tolerance sized to CI scheduling jitter (seconds, not 100 ms). Bumping the constant alone converts a sharp flake into a rare one. ## Not measured How often this recurs, and whether other wall-clock assertions in the same suite share the pattern. I have not swept for them.
Mos closed this issue 2026-08-07 05:33:39 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1090