Files
stack/packages/bus/src/tester-cli.mjs
jason.woltje 041e163d3c tester-cli: load the bus client only in the nonce child (P19 #876)
The tester-cli test makes about 20 Console reads and chat calls in a
row. Each one spawns TESTER_CLI, which re-executes itself so the nonce
is in its initial environment; both processes statically imported the
client and the broker module graph behind it, though the parent only
spawns the child. The child now imports Client and readProcess after
the re-exec branch, so the parent is a bare node start. Interleaved
over 20 calls at load 19: 258 ms per call before, 192 ms after. The
proof, nonce and argv are unchanged.

What remains is legitimate serial work: about 20 round trips of two
node processes each, about 3 s idle and 10 s at load 20 on 16 cores
(before this change). 30 s left under 3x room on a busy machine, so the
test's hang guard is now 60 s.
2026-11-08 20:45:23 -06:00

44 lines
1.7 KiB
JavaScript

// Row 110 (#1604): the tester's transport shim, human-cli.mjs with its own nonce variable and a
// tester proof. Not a second product CLI. Input and proof never carry service tokens.
import { randomBytes } from 'node:crypto';
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { readFileSync } from 'node:fs';
const file = fileURLToPath(import.meta.url);
if (!process.env.MOSAIC_BUS_TESTER_NONCE) {
const child = spawnSync(process.execPath, [file, ...process.argv.slice(2)], {
stdio: 'inherit',
env: { ...process.env, MOSAIC_BUS_TESTER_NONCE: randomBytes(32).toString('hex') },
});
process.exit(child.status ?? 2);
}
// P19 #876: only the re-executed child, whose initial environment holds the nonce, talks to the
// bus. Loading the client (and the broker module graph behind it) here instead of at the top
// keeps the re-exec parent to a bare node start.
const { Client } = await import('./client.mjs');
const { readProcess } = await import('./human.mjs');
try {
const request = JSON.parse(readFileSync(0, 'utf8'));
if (
!request ||
typeof request !== 'object' ||
Object.keys(request).some((k) => !['business', 'verb', 'args'].includes(k))
)
throw Error();
const me = readProcess(process.pid);
const client = new Client({
path: process.argv[2],
tester: {
business: request.business,
pid: me.pid,
startTime: me.startTime,
nonce: process.env.MOSAIC_BUS_TESTER_NONCE,
},
});
const result = await client.call(request.verb, request.args ?? {});
process.stdout.write(JSON.stringify(result) + '\n');
} catch (e) {
process.stderr.write((/^[a-z-]{1,64}$/.test(e.code ?? '') ? e.code : 'invalid-request') + '\n');
process.exitCode = 2;
}