Skip to content

Commit 1f46ea1

Browse files
claude[bot]claude
andauthored
test(driver-turso): await the "remote was reached" latch instead of sampling a request counter (#17121) (#17282)
* test(driver-turso): await the "remote was reached" latch instead of sampling a request counter `turso-driver-timeout.test.ts` asserted "the remote really was reached" by reading a request COUNTER at the instant the 100 ms window closed, twice. The sample instant is chosen by the very timer under test, and libuv runs the TIMERS phase before the POLL phase: any stall that spans the window delivers the abort -- and every assertion that follows it -- before the server's already-arrived bytes are parsed into a `request` event. The counter then reads 0 for a request that is demonstrably on the wire, and the file fails as `expected 0 to be greater than 0` from a merge-queue runner, presenting as a behaviour regression when it is a load artefact. Measured on the fixture, freezing the loop 300 ms from the moment undici publishes `undici:client:sendHeaders`: 6/6 runs read the counter as 0 while `undici:client:sendHeaders` had fired, the server had accepted the connection, and the request handler dispatched ~2 ms AFTER the assertion would have run. The driver answered TIMEOUT / 504 in every one of them, so the competing hypothesis -- a 504 for a request that never left the process -- is excluded under this reproduction. The fixture now exposes a latching `firstRequest` promise the tests AWAIT, and the positive case proves reachability with an UNBOUNDED driver before the timed one runs. A window may legitimately close before its own request is issued, so "this timed request reached the remote" is not a promise the timed operation can be made to keep; "this fixture is a remote the transport reaches" is, off the timed path, and that is the anti-vacuity guard the case needs. Every product assertion is unchanged: the envelope (TIMEOUT / 504), the message, the elapsed bound, and the three negative controls all still pin what they pinned. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XTBcV7zZHmokdyQgXjbyEU * test(driver-turso): name the bound in the latch assertion's failure message A red from a sampled counter reads `expected 0 to be greater than 0`, which names no duration -- and merge-queue triage classifies a red by asking exactly that, so the flake this file produced was read as a behaviour regression. Both latch assertions now carry a message naming the bound they missed, so the red says in words that a duration went unmet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XTBcV7zZHmokdyQgXjbyEU --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3cbcedb commit 1f46ea1

1 file changed

Lines changed: 73 additions & 8 deletions

File tree

‎packages/drivers/driver-turso/src/turso-driver-timeout.test.ts‎

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,31 @@
1919
* the awaited `sync()` itself. A stub client whose `sync()` never settles is
2020
* the stalled remote.
2121
*
22+
* "The remote was reached" is an AWAITED LATCH here, never a sampled counter.
23+
* The sample instant would be chosen by the very timer under test, and libuv
24+
* runs the TIMERS phase before the POLL phase: a stall that spans the window
25+
* delivers the abort — and every assertion that follows it — before the
26+
* server's already-arrived bytes are parsed into a `request` event. A counter
27+
* read there says 0 about a request that is demonstrably on the wire. Measured
28+
* on this fixture, with the loop frozen 300 ms from the moment undici publishes
29+
* `undici:client:sendHeaders`: the counter reads 0 in 6/6 runs while the
30+
* handler dispatches ~2 ms after the assertion would have run, every time.
31+
*
32+
* The positive case takes that one step further and proves reachability with an
33+
* UNBOUNDED driver BEFORE the timed one runs. A window may legitimately close
34+
* before its own request is issued — under a long enough stall the deadline is
35+
* already spent when the transport gets its turn, and no implementation could
36+
* have put bytes on the wire — so "this timed request reached the remote" is
37+
* not something the timed operation can be made to promise. "This fixture is a
38+
* remote the transport reaches" is, off the timed path, and that is the
39+
* anti-vacuity guard the case actually needs.
40+
*
41+
* Both latch assertions carry a failure message naming their bound, so a red
42+
* says in words that a DURATION went unmet. Merge-queue triage classifies a red
43+
* by asking whether the assertion names a duration; a bare `expected 0 to be
44+
* greater than 0` from a sampled counter answers no and is read as a behaviour
45+
* regression, which is exactly how this file's flake was first read.
46+
*
2247
* Each arm carries a NEGATIVE control — the same stalled remote with no
2348
* `timeout` (and, on the replica arm, `timeout: 0`, the documented "no bound")
2449
* is still pending well past the window — so the failure the positive case
@@ -38,6 +63,14 @@ import { TursoDriver } from './turso-driver';
3863
const WINDOW_MS = 100;
3964
const CONTROL_WAIT_MS = 1000;
4065
const ELAPSED_BOUND_MS = 5000;
66+
/**
67+
* The bound on the AWAITED "the transport reached the fixture" latch. It is not
68+
* a budget any assertion measures — the condition holds in ~2 ms on an idle box
69+
* and in at most ~38 ms measured under six CPU hogs on four cores — it is the
70+
* point past which "nothing is reaching this server at all" is the only reading
71+
* left. vitest's own 5 s per-test timeout is the backstop behind it.
72+
*/
73+
const REACH_BOUND_MS = 2000;
4174

4275
const PENDING = Symbol('still pending');
4376

@@ -50,6 +83,11 @@ function stillPendingAfter<T>(operation: Promise<T>, ms: number): Promise<T | ty
5083
return Promise.race([operation, window]).finally(() => clearTimeout(timer));
5184
}
5285

86+
/** Whether `signal` has settled within `ms` — an AWAITED condition, never a sampled one. */
87+
async function settlesWithin(signal: Promise<unknown>, ms: number): Promise<boolean> {
88+
return (await stillPendingAfter(signal, ms)) !== PENDING;
89+
}
90+
5391
/** The rejection an operation produced, or `null` when it resolved. */
5492
function failureOf<T>(operation: Promise<T>): Promise<(Error & { code?: string; status?: number }) | null> {
5593
return operation.then(
@@ -61,18 +99,26 @@ function failureOf<T>(operation: Promise<T>): Promise<(Error & { code?: string;
6199
/**
62100
* A remote that accepts every TCP connection and never writes a byte back —
63101
* the shape of a stalled Turso endpoint as the driver's HTTP transport sees it.
102+
*
103+
* `firstRequest` LATCHES: it resolves the moment this server has dispatched a
104+
* request handler — whenever that is — and stays resolved. A counter read at
105+
* one instant cannot make that statement, because the instant is chosen by the
106+
* very timer under test; see the header note on phase ordering.
64107
*/
65-
async function stalledHttpServer(): Promise<{ url: string; requests: () => number; close: () => Promise<void> }> {
66-
let requests = 0;
108+
async function stalledHttpServer(): Promise<{ url: string; firstRequest: Promise<void>; close: () => Promise<void> }> {
109+
let reached!: () => void;
110+
const firstRequest = new Promise<void>((resolve) => {
111+
reached = resolve;
112+
});
67113
const server: Server = createServer(() => {
68-
requests += 1;
114+
reached();
69115
// Deliberately no response: the request hangs until the socket is torn down.
70116
});
71117
await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve));
72118
const { port } = server.address() as AddressInfo;
73119
return {
74120
url: `http://127.0.0.1:${port}`,
75-
requests: () => requests,
121+
firstRequest,
76122
close: () =>
77123
new Promise<void>((resolve) => {
78124
server.closeAllConnections();
@@ -102,6 +148,23 @@ describe('TursoDriverConfig.timeout — remote mode over HTTP', () => {
102148
const remote = await stalledHttpServer();
103149
cleanups.push(remote.close);
104150

151+
// PREMISE, established OFF the timed path: this fixture really is a remote
152+
// that the driver's HTTP transport reaches, so the refusal measured below
153+
// is a window closing on a live conversation and not a green run against a
154+
// server nobody ever dialled. It is proved with an UNBOUNDED driver —
155+
// nothing can preempt its request — which is what makes the latch an
156+
// awaited condition rather than a race. A fixture nothing reaches still
157+
// fails here, loudly, which is the whole job of this line.
158+
const reachable = new TursoDriver({ url: remote.url });
159+
await reachable.connect();
160+
cleanups.push(() => reachable.disconnect());
161+
// Settles only when the fixture tears the socket down; nobody reads that.
162+
reachable.find('probe', {}).catch(() => {});
163+
expect(
164+
await settlesWithin(remote.firstRequest, REACH_BOUND_MS),
165+
`the HTTP transport did not reach the stalled fixture within ${REACH_BOUND_MS} ms`,
166+
).toBe(true);
167+
105168
const driver = new TursoDriver({ url: remote.url, timeout: WINDOW_MS });
106169
expect(driver.transportMode).toBe('remote');
107170
await driver.connect();
@@ -117,9 +180,6 @@ describe('TursoDriverConfig.timeout — remote mode over HTTP', () => {
117180
expect(failure!.message).toContain(`${WINDOW_MS} ms`);
118181
expect(failure!.message).toContain('TursoDriverConfig.timeout');
119182
expect(elapsed).toBeLessThan(ELAPSED_BOUND_MS);
120-
// The remote really was reached — the window closed a live request, not a
121-
// connection that never happened.
122-
expect(remote.requests()).toBeGreaterThan(0);
123183
});
124184

125185
it('NEGATIVE CONTROL: with no timeout the same stalled remote leaves the operation pending', async () => {
@@ -135,7 +195,12 @@ describe('TursoDriverConfig.timeout — remote mode over HTTP', () => {
135195
operation.catch(() => {});
136196

137197
expect(await stillPendingAfter(operation, CONTROL_WAIT_MS)).toBe(PENDING);
138-
expect(remote.requests()).toBeGreaterThan(0);
198+
// Same latch, same reason: nothing bounds this operation, so the request is
199+
// reached and the condition is awaited, never sampled at a chosen instant.
200+
expect(
201+
await settlesWithin(remote.firstRequest, REACH_BOUND_MS),
202+
`the HTTP transport did not reach the stalled fixture within ${REACH_BOUND_MS} ms`,
203+
).toBe(true);
139204
});
140205
});
141206

0 commit comments

Comments
 (0)