Update Healer Man server

This commit is contained in:
phenom committed 2026-09-19 14:33:15 -04:00
1 parent a05a79eb83
commit f8314e7de1
14 files changed
+529 -108

No files matched your search

+10 -3
View File
@@ -227,6 +227,15 @@ function lineCollector(onLine) {
};
}
function processFailureMessage(job, code) {
if (job.logTail.some((line) => line.includes("ENOSPC: System limit for number of file watchers reached"))) {
return "Balance Lab could not start because the server file-watcher limit was exhausted.";
}
return code === 0
? "Balance Lab ended without producing its suite report."
: `Balance Lab process exited with code ${code ?? "unknown"}.`;
}
export function createBalanceLabJobService(options = {}) {
const projectRoot = path.resolve(options.projectRoot ?? fileURLToPath(new URL("..", import.meta.url)));
const dataDir = path.resolve(options.dataDir ?? process.env.DATA_DIR ?? "data/runtime");
@@ -411,9 +420,7 @@ export function createBalanceLabJobService(options = {}) {
} else {
job.status = "failed";
job.error = error?.message
?? (code === 0
? "Balance Lab ended without producing its suite report."
: `Balance Lab process exited with code ${code ?? "unknown"}.`);
?? processFailureMessage(job, code);
}
persistJob(job);
pump();
+43
View File
@@ -5,6 +5,7 @@ import os from "node:os";
import path from "node:path";
import { PassThrough } from "node:stream";
import test from "node:test";
import { resolveConfig } from "vite";
import {
balanceLabCommand,
createBalanceLabJobService,
@@ -13,6 +14,12 @@ import {
normalizeBalanceLabJobSpec,
} from "./balance-lab-jobs.mjs";
test("disables public assets and filesystem watching in Balance Lab Vite mode", async () => {
const config = await resolveConfig({ server: { watch: null } }, "serve", "balance-lab");
assert.equal(config.publicDir, "");
assert.deepEqual(config.server.watch?.ignored, ["**/*"]);
});
test("normalizes and bounds server Balance Lab requests", () => {
const spec = normalizeBalanceLabJobSpec({
source: "ALL",
@@ -155,6 +162,42 @@ test("queues a job, reports progress, and exposes only allow-listed artifacts",
}
});
test("reports exhausted file watchers as a specific startup failure", async () => {
const directory = mkdtempSync(path.join(os.tmpdir(), "healer-man-balance-watchers-"));
try {
const spawnProcess = () => {
const child = new EventEmitter();
child.stdout = new PassThrough();
child.stderr = new PassThrough();
child.kill = () => child.emit("close", null);
setImmediate(() => {
child.stderr.write("Error: ENOSPC: System limit for number of file watchers reached, watch '/app/public/assets/example'\n");
child.stdout.end();
child.stderr.end();
child.emit("close", 1);
});
return child;
};
const service = createBalanceLabJobService({
dataDir: directory,
projectRoot: directory,
spawnProcess,
pythonExecutable: "python-test",
});
const started = service.start({
source: "wow", level: 40, partyConfigurations: 1, simulationsPerParty: 1,
durationSeconds: 5, partySeed: 1, bossCategory: "all", bossKeys: ["gundrak/entry-29932"],
}, { username: "Phenom" });
await new Promise((resolve) => setImmediate(resolve));
const failed = service.get(started.id);
assert.equal(failed.status, "failed");
assert.match(failed.error, /file-watcher limit was exhausted/i);
service.close();
} finally {
rmSync(directory, { recursive: true, force: true });
}
});
test("restores completed reports as previous runs after a server restart", async () => {
const directory = mkdtempSync(path.join(os.tmpdir(), "healer-man-balance-history-"));
try {