infra/build-server/capacity: igneum-capacity.service (user build, Nice 19, SCHED_IDLE, CPUQuota leaving 8 threads free) runs run.sh, a controller over a priority queue of jobs that pauses (SIGSTOP) the instant a build slot or the measure hold is taken (5 s poll of /srv/builds/_locks) and resumes after. Jobs, each with a dry-run and a 10-min smoke: pow fuzz (continuous, seed base advances), sync-request fuzz against a throwaway pruned node on loopback (the Horizon 28-unwrap gate, igneum-p2p-probe sync-fuzz), GHOSTDAG and finality sweeps seeds 1 to 1,000, model.py sweeps cached, clippy+audit per recent branch. Summaries to /srv/workers/capacity.json; the worker dashboard gains a Background lane (collect.mjs doc.background, page renderBackground). Night battery stops and restarts the layer. docs/plans/build-server.md section 8. igneum-pow fuzz tests and ghostdag_sim.py / attacks.py gain a seed-base knob for the continuous sweeps. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
72 lines
2.9 KiB
JavaScript
Executable file
72 lines
2.9 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
// The capacity layer's summary writer. Atomically merges one JSON fragment into /srv/workers/capacity.json, the file
|
|
// the worker dashboard's collector (tools/workers/collect.mjs) reads for the "Background" lane. Never takes a build
|
|
// slot, never writes anywhere but IGNEUM_CAPACITY_JSON. Node 22, no deps.
|
|
//
|
|
// echo '{"state":"running","summary":"...","counters":{...}}' | summary.mjs job pow-fuzz
|
|
// merge the fragment into doc.jobs["pow-fuzz"], stamping updated_at; set doc.jobs[job].priority from CAP_PRIORITY if given
|
|
// echo '{"state":"running","current_job":"pow-fuzz","paused_reason":null}' | summary.mjs controller
|
|
// merge the fragment into the top-level controller fields (state, current_job, paused_reason, slice, host)
|
|
// summary.mjs init write an empty document if none exists
|
|
//
|
|
// The document:
|
|
// { v, generated_at, host, state, current_job, paused_reason, slice_s,
|
|
// jobs: { <job>: { priority, state, updated_at, summary, counters, panics, saved, ... } } }
|
|
import { readFileSync, writeFileSync, renameSync, mkdirSync } from 'node:fs';
|
|
import { dirname } from 'node:path';
|
|
import { hostname } from 'node:os';
|
|
|
|
const OUT = process.env.IGNEUM_CAPACITY_JSON || '/srv/workers/capacity.json';
|
|
const iso = () => new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
|
|
function load() {
|
|
try {
|
|
const d = JSON.parse(readFileSync(OUT, 'utf8'));
|
|
if (d && typeof d === 'object') { d.jobs = d.jobs || {}; return d; }
|
|
} catch { /* fall through to a fresh document */ }
|
|
return { v: 1, host: hostname(), state: 'starting', current_job: null, paused_reason: null, slice_s: null, jobs: {} };
|
|
}
|
|
|
|
function save(d) {
|
|
d.v = 1; d.host = d.host || hostname(); d.generated_at = iso();
|
|
mkdirSync(dirname(OUT), { recursive: true });
|
|
const tmp = OUT + '.tmp';
|
|
writeFileSync(tmp, JSON.stringify(d));
|
|
renameSync(tmp, OUT);
|
|
}
|
|
|
|
function readStdin() {
|
|
try {
|
|
const t = readFileSync(0, 'utf8').trim();
|
|
if (!t) return {};
|
|
const o = JSON.parse(t);
|
|
return o && typeof o === 'object' ? o : {};
|
|
} catch (e) { process.stderr.write('summary.mjs: bad JSON on stdin: ' + (e.message || e) + '\n'); process.exit(1); }
|
|
}
|
|
|
|
const mode = process.argv[2];
|
|
const d = load();
|
|
|
|
if (mode === 'init') { save(d); process.exit(0); }
|
|
|
|
if (mode === 'controller') {
|
|
const frag = readStdin();
|
|
for (const k of ['state', 'current_job', 'paused_reason', 'slice_s', 'host']) if (k in frag) d[k] = frag[k];
|
|
save(d);
|
|
process.exit(0);
|
|
}
|
|
|
|
if (mode === 'job') {
|
|
const job = process.argv[3];
|
|
if (!job) { process.stderr.write('summary.mjs job <name>\n'); process.exit(1); }
|
|
const frag = readStdin();
|
|
const prev = d.jobs[job] || {};
|
|
const merged = { ...prev, ...frag, updated_at: iso() };
|
|
if (process.env.CAP_PRIORITY) merged.priority = Number(process.env.CAP_PRIORITY);
|
|
d.jobs[job] = merged;
|
|
save(d);
|
|
process.exit(0);
|
|
}
|
|
|
|
process.stderr.write('summary.mjs: mode is one of init | controller | job <name>\n');
|
|
process.exit(1);
|