Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/flatbread/src/cli/serve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
unlink,
writeFile,
} from 'node:fs/promises';
import { createServer } from 'node:http';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { handleEffortWrite } from './proof.js';
Expand Down Expand Up @@ -300,3 +301,25 @@ test.serial(
t.regex(JSON.parse(result.stdout).summary, /^0 records/);
}
);

test.serial(
'a second server does not take the socket from a busy one',
async (t) => {
const dir = await mkdtemp(join(tmpdir(), 'flatbread-busy-'));
t.teardown(() => rm(dir, { recursive: true, force: true }));
const socket = join(dir, 'serve.sock');
// A server that accepts connections but never replies, like one
// blocked while it builds a large graph.
const busy = createServer(() => undefined);
const held = new Set<import('node:net').Socket>();
busy.on('connection', (connection) => held.add(connection));
await new Promise<void>((done) => busy.listen(socket, done));
t.teardown(() => {
for (const connection of held) connection.destroy();
busy.close();
});
await t.throwsAsync(serveProofReads(socket), {
message: /already answers on/,
});
}
);
9 changes: 7 additions & 2 deletions packages/flatbread/src/cli/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ export interface ServedRead {
readonly code: number;
}

/** True when something answers HTTP on `socketPath`. */
/**
* True when a server holds `socketPath`. A dead socket refuses the connection
* at once. A live server that is busy, such as one building a large graph,
* accepts it but may not reply within the probe's two seconds, so a timeout
* also counts as live.
*/
function answers(socketPath: string): Promise<boolean> {
return new Promise((resolveAnswer) => {
const probe = request(
Expand All @@ -60,7 +65,7 @@ function answers(socketPath: string): Promise<boolean> {
probe.on('error', () => resolveAnswer(false));
probe.setTimeout(2000, () => {
probe.destroy();
resolveAnswer(false);
resolveAnswer(true);
});
probe.end();
});
Expand Down
Loading