Release Healer Man 0.1.56

This commit is contained in:
phenom committed 2026-09-19 13:16:17 -04:00
1 parent 38b3d4d160
commit a05a79eb83
16 files changed
+388 -116

No files matched your search

+81
View File
@@ -9,6 +9,7 @@ import {
balanceLabCommand,
createBalanceLabJobService,
inspectBalanceLabRuntime,
normalizeBalanceLabJobBatch,
normalizeBalanceLabJobSpec,
} from "./balance-lab-jobs.mjs";
@@ -43,6 +44,20 @@ test("normalizes and bounds server Balance Lab requests", () => {
);
});
test("normalizes complete level batches before any jobs are queued", () => {
const batch = normalizeBalanceLabJobBatch({
specs: [10, 20, 30].map((level) => ({
source: "wow", level, partyConfigurations: 1, simulationsPerParty: 1,
durationSeconds: 5, partySeed: 1, bossCategory: "all", bossKeys: ["gundrak/entry-29932"],
})),
});
assert.deepEqual(batch.map((spec) => spec.level), [10, 20, 30]);
assert.throws(() => normalizeBalanceLabJobBatch({ specs: [] }), /must contain 1 through 80/);
assert.throws(() => normalizeBalanceLabJobBatch({
specs: [{ source: "wow", level: 10 }, { source: "wow", level: 81 }],
}), /Level must be a whole number/);
});
test("builds an argument-array command without a shell", () => {
const spec = normalizeBalanceLabJobSpec({
source: "rom", level: 60, partyConfigurations: 4, simulationsPerParty: 2,
@@ -293,3 +308,69 @@ test("bounds the number of pending server jobs", () => {
rmSync(directory, { recursive: true, force: true });
}
});
test("runs separate level jobs concurrently and reports worker utilization", () => {
const directory = mkdtempSync(path.join(os.tmpdir(), "healer-man-balance-parallel-"));
try {
let launches = 0;
const spawnProcess = () => {
launches += 1;
const child = new EventEmitter();
child.stdout = new PassThrough();
child.stderr = new PassThrough();
child.kill = () => child.emit("close", null);
return child;
};
const service = createBalanceLabJobService({
dataDir: directory,
projectRoot: directory,
spawnProcess,
pythonExecutable: "python-test",
maxConcurrent: 3,
maxQueued: 10,
});
const requestForLevel = (level) => ({
source: "wow", level, partyConfigurations: 1, simulationsPerParty: 1,
durationSeconds: 5, partySeed: 1, bossCategory: "all", bossKeys: ["gundrak/entry-29932"],
});
const jobs = service.startMany({ specs: [10, 20, 30].map(requestForLevel) }, { username: "Phenom" });
assert.equal(launches, 3);
assert.deepEqual(jobs.map((job) => job.status), ["running", "running", "running"]);
assert.deepEqual(jobs.map((job) => job.spec.level), [10, 20, 30]);
assert.deepEqual(service.runtime(), {
available: true,
executable: "python-test",
version: "test process",
error: null,
maxConcurrent: 3,
running: 3,
queued: 0,
maxQueued: 10,
});
service.close();
} finally {
rmSync(directory, { recursive: true, force: true });
}
});
test("rejects an oversized batch without queueing a partial sweep", () => {
const directory = mkdtempSync(path.join(os.tmpdir(), "healer-man-balance-batch-capacity-"));
try {
const service = createBalanceLabJobService({
dataDir: directory,
projectRoot: directory,
spawnProcess: () => { throw new Error("an over-capacity batch must not launch"); },
pythonExecutable: "python-test",
maxQueued: 2,
});
const specs = [10, 20, 30].map((level) => ({
source: "wow", level, partyConfigurations: 1, simulationsPerParty: 1,
durationSeconds: 5, partySeed: 1, bossCategory: "all", bossKeys: ["gundrak/entry-29932"],
}));
assert.throws(() => service.startMany({ specs }, { username: "Phenom" }), /server queue is full/);
assert.equal(service.list().length, 0);
service.close();
} finally {
rmSync(directory, { recursive: true, force: true });
}
});