feat(api): place fleet boxes by boxes per slot (#420)

Fleet placement picked the online machine with the fewest boxes,
whatever its capacity. A box never moves, so a two-slot host got as many
people as an eight-slot one and queued while the bigger one idled.

Now it picks the fewest boxes per slot (the `slots` each host reports in
its heartbeat). A host that reports none counts as one slot, so today's
fleet behaves as before.

- New test: a 2-slot and an 8-slot machine, five people, four land on
the bigger one.
- api 194, core 256 pass.
This commit is contained in:
Wanjohi
2026-10-17 12:55:49 +03:00
committed by GitHub
parent c4bb12db6a
commit fe2b8d6e35
2 changed files with 42 additions and 5 deletions
+16
View File
@@ -84,6 +84,22 @@ describe('POST /box on the fleet', () => {
expect(boxB.machineId).toBe(second!.id);
});
test('places by boxes per slot, so a bigger machine takes more people', async () => {
const f = await fleet(2);
useFleet(f.organisationId);
const [small, big] = f.machines;
await sql`update machine set slots = 2 where id = ${small!.id}`;
await sql`update machine set slots = 8 where id = ${big!.id}`;
const placed: string[] = [];
for (let i = 0; i < 5; i++) {
const p = await person(`fleet-slots-${i}`);
placed.push(((await (await createBox(p.headers, { on: 'fleet' })).json()) as any).data.machineId);
}
// small first on the tie at 0, then big until it is as full per slot.
expect(placed).toEqual([small!.id, big!.id, big!.id, big!.id, big!.id]);
});
test('skips a fleet machine that is offline', async () => {
const f = await fleet(2);
useFleet(f.organisationId);