Skip to content

Commit e3645e0

Browse files
fix(e2e): pin /nosql/new to fast anon hot-pool to stop e2e-prod timeout flake (#180)
nosql was the LAST dedicated-backing-DB service still on the slow authed (minted-pro) provision path. The authed /nosql/new path provisions a DEDICATED MongoDB per team — cold-provision > 90s on prod — which timed out the LIVE suite at the per-test limit (flaky run 27000380873 failed on /nosql/new; an earlier run failed on /vector/new). Prior PRs pinned db (#178) + queue (#177) + vector (#179) to the fast anon hot-pool; this completes the set. Systemic fix: EVERY service whose authed path provisions a dedicated backing DB (db/vector/nosql) now uses forceAnon (anon hot-pool, TTL-reaped), so none can hit the slow authed-dedicated-provision timeout. The fast, no-dedicated-DB services (cache/storage/webhook) stay on the authed/minted-account + authed-reap path, and the auth specs + claim flow + minted-account lifecycle keep exercising the on-the-fly minted account — "test accounts on the fly" coverage is retained. Adds a per-service path table (dedicated-DB? + fast-authed vs anon-hot-pool + why) to live-anon-provision.spec.ts and syncs the cohort.ts/smoke-spec comments. Secondary guard: bump playwright.live.config.ts per-test timeout 90s → 120s for extra cold-hot-pool/network headroom (the forceAnon pinning is the primary fix). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 89e6b1b commit e3645e0

4 files changed

Lines changed: 74 additions & 37 deletions

File tree

e2e/cohort.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,19 +275,21 @@ export const ANON_TIER = 'anonymous'
275275
*
276276
* `forceAnon` pins the anonymous fast-hot-pool path even when a minted session
277277
* exists. Used wherever the AUTHED prod provision is too slow / hangs to finish
278-
* inside the LIVE per-test timeout (playwright.live.config.ts, 90s):
279-
* - DB & VECTOR: the authed (pro) /db/new & /vector/new paths provision a
280-
* DEDICATED Postgres / pgvector Postgres for the team — slow on prod (15s
281-
* warm, >90s cold). The anon path uses the fast (pgvector) hot-pool.
278+
* inside the LIVE per-test timeout (playwright.live.config.ts):
279+
* - DB, VECTOR & NOSQL: the authed (pro) /db/new, /vector/new & /nosql/new
280+
* paths each provision a DEDICATED backing DB for the team (Postgres /
281+
* pgvector Postgres / MongoDB) — slow on prod (15s warm, >90s cold). The
282+
* anon path uses the fast hot-pool. These are ALL the dedicated-backing-DB
283+
* services; none may hit the slow authed-dedicated-provision path.
282284
* - QUEUE: the authed /queue/new isolated per-tenant NATS path HANGS on prod
283285
* until the operator seeds the NATS operator/sys NKeys (CLAUDE.md P1 known
284286
* gap). The anon path returns fast with auth_mode=legacy_open.
285287
* In every forceAnon case the resulting anon resource is reaped by its 24h TTL
286288
* (no authed DELETE exists for anon resources); the spec treats a no-bearer
287289
* resource's reap as best-effort (TTL-backed) rather than asserting a 200 it can
288-
* never get. The genuinely-fast services (cache/nosql/storage/webhook) stay on
289-
* the authed-minted path so the authed/minted-account + authed-reap legs are
290-
* still exercised.
290+
* never get. The genuinely-fast services (cache/storage/webhook) have NO
291+
* dedicated backing DB and stay on the authed-minted path so the
292+
* authed/minted-account + authed-reap legs are still exercised.
291293
*/
292294
export function provisionIdentity(
293295
extra: Record<string, string> = {},

e2e/live-anon-provision.spec.ts

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,16 @@ interface ProvisionFlow {
8080
/** Optional extra per-service assertion on the parsed JSON body. */
8181
extra?: (body: Record<string, unknown>) => void
8282
/**
83-
* Pin the anonymous bypass path even when a minted pro session exists. Only
84-
* `queue` sets this: the authed /queue/new path attempts isolated per-tenant
85-
* NATS provisioning which HANGS on prod (operator NKeys unseeded — CLAUDE.md
86-
* P1). The anon path returns fast with auth_mode=legacy_open; the anon
87-
* resource is TTL-reaped (no authed DELETE for anon resources).
83+
* Pin the anonymous bypass path even when a minted pro session exists. Set by
84+
* every service whose authed path is too slow / hangs to finish inside the
85+
* per-test timeout:
86+
* - `vector` & `nosql`: the authed path provisions a DEDICATED backing DB
87+
* (pgvector Postgres / MongoDB) for the team — cold-provision > 90s on
88+
* prod. (`db` does the same in the smoke spec.)
89+
* - `queue`: the authed /queue/new path attempts isolated per-tenant NATS
90+
* provisioning which HANGS on prod (operator NKeys unseeded — CLAUDE.md P1).
91+
* The anon path returns fast (hot-pool / legacy_open); the anon resource is
92+
* TTL-reaped (no authed DELETE for anon resources).
8893
*/
8994
forceAnon?: boolean
9095
}
@@ -97,29 +102,44 @@ interface ProvisionFlow {
97102
// Each flow runs as EITHER the minted PRO account (authed, exercises the
98103
// minted-account/authed-reap path) OR the anonymous fast-hot-pool path
99104
// (forceAnon). The deciding factor is whether the AUTHED prod provision is fast
100-
// enough to finish inside the 90s per-test timeout (playwright.live.config.ts):
105+
// enough to finish inside the per-test timeout (playwright.live.config.ts):
101106
//
102-
// service | path | why
103-
// ---------|----------------|----------------------------------------------
104-
// db | anon (forceAnon, in smoke spec) | authed = DEDICATED Postgres,
105-
// | | cold-provision > 90s on prod; anon = hot-pool (fast)
106-
// vector | anon (forceAnon)| authed = DEDICATED pgvector Postgres, same
107-
// | | slow dedicated-provision as db (15s warm, >90s
108-
// | | cold) → TIMED OUT the suite (run 26999448643).
109-
// | | anon = fast hot-pool; anon resource TTL-reaped.
110-
// queue | anon (forceAnon)| authed isolated-NATS path HANGS on prod (P1
111-
// | | NKeys gap); anon returns fast (legacy_open).
112-
// cache | authed-minted | Redis provision is fast (no dedicated DB build);
113-
// | | KEEPS authed/minted-account + authed-reap coverage.
114-
// nosql | authed-minted | Mongo provision is fast; KEEPS authed coverage.
115-
// storage | authed-minted | DO Spaces tenant-prefix (no DB build) → fast;
116-
// | | KEEPS authed coverage.
117-
// webhook | authed-minted | Redis-backed receiver, fast; KEEPS authed coverage.
107+
// service | path | backing DB? | why
108+
// ---------|----------------|--------------|-------------------------------
109+
// db | ANON (forceAnon, in smoke spec) | DEDICATED Postgres | authed
110+
// | | | cold-provision > 90s on prod;
111+
// | | | anon = hot-pool (fast).
112+
// vector | ANON (forceAnon)| DEDICATED pgvector Postgres | same slow
113+
// | | | dedicated-provision as db (15s
114+
// | | | warm, >90s cold) → TIMED OUT the
115+
// | | | suite (run 26999448643). anon =
116+
// | | | fast hot-pool; TTL-reaped.
117+
// nosql | ANON (forceAnon)| DEDICATED Mongo | authed = DEDICATED MongoDB;
118+
// | | | cold-provision > 90s on prod
119+
// | | | (run 27000380873 timed out on
120+
// | | | /nosql/new). anon = fast hot-pool;
121+
// | | | TTL-reaped. The LAST dedicated-DB
122+
// | | | service to move off the slow path.
123+
// queue | ANON (forceAnon)| none (NATS) | authed isolated-NATS path HANGS
124+
// | | | on prod (P1 NKeys gap); anon
125+
// | | | returns fast (legacy_open).
126+
// cache | authed-minted | none (Redis) | Redis provision is fast (no
127+
// | | | dedicated DB build); KEEPS authed/
128+
// | | | minted-account + authed-reap.
129+
// storage | authed-minted | none (Spaces)| DO Spaces tenant-prefix (no DB
130+
// | | | build) → fast; KEEPS authed.
131+
// webhook | authed-minted | none (Redis) | Redis-backed receiver, fast;
132+
// | | | KEEPS authed coverage.
118133
//
119-
// Net: the two genuinely-slow DEDICATED-DB provisions (db, vector) and the
120-
// hanging queue path use the fast anon hot-pool so they can NEVER exceed the
121-
// timeout; cache/nosql/storage/webhook still exercise the authed/minted-account
122-
// (and authed-reap) path. That keeps both paths covered with zero flake.
134+
// Net: EVERY service whose authed path provisions a DEDICATED backing DB
135+
// (db, vector, nosql) — plus the hanging queue path — uses the fast anon
136+
// hot-pool so it can NEVER exceed the per-test timeout. The remaining services
137+
// (cache/storage/webhook) have NO dedicated backing DB, provision fast, and
138+
// stay on the authed/minted-account (and authed-reap) path so the
139+
// minted-account + authed-reap legs are still exercised on every run. The auth
140+
// specs, the claim flow, and the minted-account lifecycle continue to exercise
141+
// the on-the-fly minted account — "test accounts on the fly" coverage is
142+
// retained. Both paths covered, zero dedicated-DB-provision flake.
123143
const PROVISION_FLOWS: ProvisionFlow[] = [
124144
{
125145
label: 'vector',
@@ -147,6 +167,14 @@ const PROVISION_FLOWS: ProvisionFlow[] = [
147167
path: '/nosql/new',
148168
connKey: 'connection_url',
149169
connPattern: /^mongodb(\+srv)?:\/\//,
170+
// Pin anon: the authed (pro) /nosql/new path provisions a DEDICATED MongoDB
171+
// for the team — slow on prod (>90s cold), which timed out the suite at the
172+
// per-test limit (flaky run 27000380873 failed on /nosql/new). The anon path
173+
// uses the fast Mongo hot-pool and returns quickly; the anon resource is
174+
// TTL-reaped (no authed DELETE for anon resources). Same treatment as /db/new
175+
// and /vector/new — all three are dedicated-DB provisions. nosql was the LAST
176+
// dedicated-DB service still on the slow authed path.
177+
forceAnon: true,
150178
},
151179
{
152180
label: 'queue',

e2e/live-provision-smoke.spec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,11 @@ test.describe('LIVE smoke — anonymous provision → backend-assert → reap',
101101
// anon path does cleanly: the X-E2E-Test-Token + X-E2E-Source-IP fingerprint
102102
// bypass gets past the recycle gate (fresh fingerprint per call), and the
103103
// anon resource is TTL-reaped (no authed DELETE for anon resources — the
104-
// reap below is best-effort for the no-bearer case). The full authed-provision
105-
// coverage lives in live-anon-provision.spec.ts (vector/cache/nosql as the
106-
// minted pro account). /db/new REQUIRES a name (CLAUDE.md) — sent below.
104+
// reap below is best-effort for the no-bearer case). The authed/minted-account
105+
// (and authed-reap) coverage lives in live-anon-provision.spec.ts via the
106+
// fast, no-dedicated-DB services (cache/storage/webhook); the dedicated-DB
107+
// services (db/vector/nosql) all use the fast anon hot-pool there too.
108+
// /db/new REQUIRES a name (CLAUDE.md) — sent below.
107109
const id = provisionIdentity({}, /* forceAnon */ true)
108110
const resp = await request.fetch(`${API_URL}/db/new`, {
109111
method: 'POST',

playwright.live.config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ export default defineConfig({
3636
forbidOnly: !!process.env.CI,
3737
retries: process.env.CI ? 1 : 0,
3838
workers: 1,
39-
timeout: 90_000,
39+
// 120s per test (was 90s). Secondary guard only: the PRIMARY fix is pinning
40+
// every dedicated-backing-DB provision (db/vector/nosql) to the fast anon
41+
// hot-pool via forceAnon (see e2e/cohort.ts + live-anon-provision.spec.ts) so
42+
// no test depends on a slow authed-dedicated-provision finishing in time. The
43+
// modest bump gives extra headroom for a cold hot-pool / network slowness.
44+
timeout: 120_000,
4045
expect: { timeout: 20_000 },
4146

4247
reporter: process.env.CI

0 commit comments

Comments
 (0)