Add real-time progress feedback to multi-run simulations
Switch from exec() to spawn() for streaming stderr, add onProgress callback to runner, and emit per-run progress lines from workers. CI now shows live percentage, tick count, and era during long runs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { exec } from 'node:child_process';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { writeFileSync } from 'node:fs';
|
||||
import { resolve as pathResolve, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@@ -74,20 +74,30 @@ interface WorkerResult {
|
||||
function spawnWorker(runId: number, seed: number): Promise<WorkerResult> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const workerPath = new URL('./worker.ts', import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1');
|
||||
const cmd = `npx tsx "${workerPath}" --strategy ${strategyName} --ticks ${totalTicks} --seed ${seed} --run-id ${runId}`;
|
||||
exec(cmd, { maxBuffer: 200 * 1024 * 1024 }, (error, stdout, stderr) => {
|
||||
if (stderr) process.stderr.write(stderr);
|
||||
if (error) {
|
||||
reject(new Error(`Run #${runId} (seed ${seed}) failed: ${error.message}`));
|
||||
const tsxBin = pathResolve(__dirname, '..', 'node_modules', '.bin', 'tsx');
|
||||
const child = spawn(tsxBin, [workerPath, '--strategy', strategyName, '--ticks', String(totalTicks), '--seed', String(seed), '--run-id', String(runId)], {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
|
||||
let stdout = '';
|
||||
child.stdout.on('data', (chunk: Buffer) => { stdout += chunk; });
|
||||
child.stderr.on('data', (chunk: Buffer) => { process.stderr.write(chunk); });
|
||||
|
||||
child.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(`Run #${runId} (seed ${seed}) exited with code ${code}`));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = JSON.parse(stdout) as WorkerResult;
|
||||
resolve(result);
|
||||
resolve(JSON.parse(stdout) as WorkerResult);
|
||||
} catch (e) {
|
||||
reject(new Error(`Run #${runId} (seed ${seed}) produced invalid JSON: ${(e as Error).message}`));
|
||||
}
|
||||
});
|
||||
|
||||
child.on('error', (err) => {
|
||||
reject(new Error(`Run #${runId} (seed ${seed}) failed to spawn: ${err.message}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user