From 2fc0dcd6b1d6efbd973e24d0bc2dd0f2f65590a6 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Tue, 20 Oct 2026 17:10:18 -0700 Subject: [PATCH] test(daemon): run the stalled-reader backpressure test over a Unix socket, not TCP loopback (#31256) * test(daemon): run the stalled-reader backpressure test over a Unix socket, not TCP loopback Linux autotunes TCP loopback buffers to several MiB, so the kernel absorbed most of the 8 MiB flood, write callbacks completed, and the producer never reached the 4 MiB high-water mark on some CI runners. The daemon stream runs over a Unix socket or named pipe, whose small fixed kernel buffers keep the backlog in the daemon's own accounting. * test(daemon): bound Unix socket fixture paths --- .../daemon-stream-backpressure-socket.test.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/daemon/daemon-stream-backpressure-socket.test.ts b/src/main/daemon/daemon-stream-backpressure-socket.test.ts index e37c6e616b4..bbd1e46f312 100644 --- a/src/main/daemon/daemon-stream-backpressure-socket.test.ts +++ b/src/main/daemon/daemon-stream-backpressure-socket.test.ts @@ -1,5 +1,8 @@ import { once } from 'node:events' +import { mkdtempSync, rmSync } from 'node:fs' import { createServer, Socket } from 'node:net' +import { tmpdir } from 'node:os' +import { basename, join } from 'node:path' import { setImmediate as nextTurn, setTimeout as delay } from 'node:timers/promises' import { describe, expect, it } from 'vitest' import { DaemonStreamDataBatcher } from './daemon-stream-data-batcher' @@ -17,6 +20,14 @@ describe('daemon stream backpressure with a stalled Socket reader', () => { ])( 'bounds $chunkSize-character writes (hidden=$hidden) and resumes', async ({ chunkSize, hidden }) => { + // Why: the daemon stream runs over a Unix socket or named pipe. Linux TCP loopback autotunes its + // kernel buffers to several MiB, enough to absorb the flood before the 4 MiB high-water mark. + // A fixed POSIX root keeps the full Unix socket path below the kernel's byte limit. + const dir = mkdtempSync(join(process.platform === 'win32' ? tmpdir() : '/tmp', 'orca-dsbp-')) + const socketPath = + process.platform === 'win32' + ? `\\\\.\\pipe\\${basename(dir)}.sock` + : join(dir, 'stream.sock') const server = createServer() const writer = new Socket() let reader: Socket | undefined @@ -42,13 +53,9 @@ describe('daemon stream backpressure with a stalled Socket reader', () => { writer.on('drain', () => batcher.flush('client')) try { const accepted = once(server, 'connection') - server.listen(0, '127.0.0.1') + server.listen(socketPath) await once(server, 'listening') - const address = server.address() - if (!address || typeof address === 'string') { - throw new Error('Expected TCP address') - } - writer.connect(address.port, '127.0.0.1') + writer.connect(socketPath) await once(writer, 'connect') const [acceptedSocket] = await accepted if (!(acceptedSocket instanceof Socket)) { @@ -139,6 +146,7 @@ describe('daemon stream backpressure with a stalled Socket reader', () => { writer.destroy() reader?.destroy() await new Promise((resolve) => server.close(() => resolve())) + rmSync(dir, { recursive: true, force: true }) } } )