Skip to content

test(driver-sql): sql-driver-connect-bound runs under the 10 s budget (#23182 row 6) - #23812

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23182-connect-bound-budget
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23182-connect-bound-budget

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #23182 (row 6)

Row 6 of the test-budget card: packages/drivers/driver-sql/src/sql-driver-connect-bound.test.ts, read at 10.5 s in the hourly full battery (run 38228297391). Test-only change, one file. The seat closes the card; this PR does not.

Where the time went

One test of sixteen: actually bounds a query against a black-holing endpoint waited out the driver's real 10 s pg connectionTimeoutMillis against a loopback listener that accepts the socket and never answers. That is 10,014-10,015 ms of the file's 10.14-10.20 s of test time (3 runs, alone). The other fifteen tests total about 0.2 s.

The 10 s is the production default (DEFAULT_CONNECT_TIMEOUT_MS, a private static with no seam), and the card's limits forbid shortening the bound the test pins. PR #23730 (the sqlite connect fail-fast) changed only the sqlite connect path in sql-driver.ts, not the pg bound this test waits on: re-measured on current main, the wait is unchanged. So the fix is the test's clock, not production.

What changed

  • The listener stays real (same loopback black hole). A new accepted promise settles when the server holds the first socket.
  • setTimeout and clearTimeout are faked for the test body only (vi.useFakeTimers with an explicit toFake; net I/O, microtasks and Date stay real). pg arms connectionTimeoutMillis and tarn arms createTimeoutMillis on the faked setTimeout.
  • The test does not move the clock until the server has accepted the socket, then advances it in 500 ms steps (each followed by a real macrotask yield) until the query settles, never past 20 s.
  • Real timers are restored in finally, before afterEach disconnects the driver.
  • The per-test timeout goes from 40,000 to 15,000 ms: it only has to bound a hung run now. Lowered, not raised.
  • The two settlement outcomes are tracked explicitly, so a query that resolves is reported as "resolved but should have failed", not as "still pending".

Every pinned behaviour stays pinned

Same assertions on the black-hole test: message contains timeout expired, message does not contain pool is probably full, elapsed greater than 8,000 and less than 20,000. Elapsed is now the fake clock's advance, which is exact: it read 10,000 in 3 probe runs against the unmodified driver (a scratch copy printing it, deleted after). Two assertions are added: one that the query settled within 20 s of fake time (what an unbounded connect fails), one that it did not resolve. The other fifteen tests are byte-identical. Tests 16 to 16; expect( calls 26 to 28. No test deleted, no .skip/.todo, no project change.

Before and after

Method: the file alone, pnpm exec vitest run --maxWorkers=2 --reporter=verbose, through scripts/pm/os-verify-lock.sh, 3 runs each, dependency closure built first. A shared box, so read the ratios.

tests (vitest tests figure) black-hole test file Duration
base 9d4fb3c306 10.20 / 10.15 / 10.14 s 10,015 / 10,014 / 10,014 ms 19.97 / 20.12 / 20.54 s
this branch, head 470d1ad3a1 131 / 136 / 132 ms 20 / 21 / 20 ms 9.47 / 9.46 / 9.32 s

The remaining Duration is vitest's cold module-graph load, not test time: import 8.8-9.0 s and transform 7.2-7.4 s on this box (not attributed further here). It cannot be what the card's 10.5 s reading counts (that reading is the 10.01 s black-hole test plus about 0.5 s), so it is outside this row.

Ablation

Mutations land on sql-driver.ts through scripts/ablation-replace.mjs (WRAP mode; each leg proved on disk: anchor 1 to 0, blob changed, then restored with blob equal to HEAD and git diff HEAD empty). The subject is imported as ./sql-driver.js, which resolves to source, so there is no dist/ leg. Each ablation was run against the base test (a scratch copy, deleted after) and this branch's test in one run; failures below are the black-hole test's.

mutation base test this branch
A: DEFAULT_CONNECT_TIMEOUT_MS 10_000 to 5_000 red, expected 5007 to be greater than 8000 (5.0 s) red, expected 5000 to be greater than 8000 (32 ms)
B: dialect timeout injection disabled (dialect forced undefined) red, expected 'Knex: Timeout acquiring a connection.…' to contain 'timeout expired' (15.0 s) red, same message (20 ms)
C: withConnectBound bypassed (no bound at all) red, same Knex message (30.0 s) red, still pending after 20s of fake time — the connect is unbounded (46 ms)

Whole-file counts under each: A 5 failed of 16, B 5 of 16, C 8 of 16 on this branch (the extra failures are the config-shape pins in the same file, identical on base). Control, unmutated: 32 of 32 across both files. Not ablated: the resolved but should have failed guard (no cheap production mutation makes a connect to a silent socket succeed).

Verification (head 470d1ad3a1)

  • pnpm --filter @objectstack/driver-sql typecheck: exit 0; tsc --noEmit --listFiles lists the test file once (the package has no test-typecheck ledger).
  • eslint, --no-inline-config, on the changed file: 1 file, 0 errors, 0 warnings.
  • node scripts/pm/dispatch-gates.mjs --commands (51) plus every artifact-roster family (53) plus every declared wide-population family (11): 114 unique commands, run at this head, recorded with exit codes. 108 exit 0. Two exited 3 on a missing dist/ (check:dual-build-cjs-loads, check:lean-entry-closure); after turbo run build (75 tasks, 74 cached) both re-ran exit 0. Four roster gates need pull-request context and answered NOT MEASURED locally: check-closing-target-claim.mjs (exit 2), pm/check-governed-queue-guard.mjs (exit 1, no event payload), check-partof-closing-keyword.mjs (exit 2; re-run below with this body), check-single-claim-paths.mjs (exit 2). Their workflows run on the PR.
  • dispatch-gates.mjs --ran over the coded record: 51 derived families accounted for, 51 run, 0 NOT-MEASURED (a derived zero: all 51 recorded an exit code, none is 3).
  • No changeset: the published files[] is dist, README.md, CHANGELOG.md, and the built dist/index.js and dist/index.mjs carry none of the test's identifiers. skip-changeset is applied through scripts/pm/label-write.mjs after opening.
  • Not measured: CI wall for the file on a runner (the hourly battery is the pin; the next refresh PR's list no longer naming the file).

Acceptance notes

  • Noted, not filed (no reproducible defect, no contract text): the cold import share of about 9 s per driver-sql test file locally. Carrier: none.

Generated by Claude Code

…clock over its real socket

The one slow test in sql-driver-connect-bound.test.ts waited out the
driver's real 10s pg connectionTimeoutMillis against a loopback listener
that accepts and never answers (10.01s of the file's 10.15s of test time,
3 runs alone). The listener stays real; only setTimeout/clearTimeout are
faked, and the clock is moved in 500ms steps until the query settles, so
the pg 10s bound, the tarn 15s backstop and an unbounded connect each
still show in how far the clock had to move. Same message and elapsed-band
assertions as before.

Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX
Co-authored-by: Claude <noreply@anthropic.com>
…so a resolved query is not read as pending

The stepping loop stopped on a captured rejection only, so a query that
RESOLVED (the "should have failed" case) would have been misreported as
"still pending after 20s". Settlement is now one of two named outcomes, and
each has its own assertion message.

Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 16, 2026
@github-actions github-actions Bot added the tests label Oct 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 74b436263a9acb0ba659dcbf426ffc3ae2eff7ff → packageMentionDocs.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 16, 2026 04:54
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 16, 2026 04:54
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit 59f9763 Oct 16, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23182-connect-bound-budget branch October 16, 2026 05:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants