Initial import of verae-fleet from zapier monorepo
This commit is contained in:
commit
1fb7f752d6
28 changed files with 1405 additions and 0 deletions
99
test/fleet.test.js
Normal file
99
test/fleet.test.js
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import { describe, it, after } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { loadFleet, listServices } from '../src/load.js';
|
||||
import { Supervisor } from '../src/supervisor.js';
|
||||
import { Monitor } from '../src/monitor.js';
|
||||
|
||||
function treeOnly(healthBase) {
|
||||
const loaded = loadFleet();
|
||||
for (const s of Object.values(loaded.services)) {
|
||||
s.enabled = s.id === 'tree-node';
|
||||
if (s.id === 'tree-node') {
|
||||
s.min = 3;
|
||||
s.max = 6;
|
||||
s.keepFloor = true;
|
||||
s.ports = { healthBase };
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
describe('verae-fleet', () => {
|
||||
/** @type {Supervisor[]} */
|
||||
const supervisors = [];
|
||||
after(async () => {
|
||||
for (const s of supervisors) await s.stopAll();
|
||||
});
|
||||
|
||||
it('lists every service with a config file and central replica spec', () => {
|
||||
const loaded = loadFleet();
|
||||
const rows = listServices(loaded);
|
||||
const ids = rows.map((r) => r.id);
|
||||
for (const need of [
|
||||
'nats',
|
||||
'zappier-edge',
|
||||
'middleware-http',
|
||||
'job-poller',
|
||||
'webhook-deliver',
|
||||
'archive-aggregator',
|
||||
'archive-worm',
|
||||
'tree-node',
|
||||
'zapier-simulator',
|
||||
'zapier-platform-app',
|
||||
]) {
|
||||
assert.ok(ids.includes(need), `missing ${need}`);
|
||||
}
|
||||
const tree = loaded.services['tree-node'];
|
||||
assert.equal(tree.min, 3);
|
||||
assert.equal(tree.keepFloor, true);
|
||||
assert.equal(tree.configPath, 'services/tree-node.json');
|
||||
assert.equal(loaded.fleetPath, 'fleet.json');
|
||||
});
|
||||
|
||||
it('starts the tree-node floor (3 available copies)', async () => {
|
||||
const sup = new Supervisor({ loaded: treeOnly(14600) });
|
||||
supervisors.push(sup);
|
||||
await sup.startService('tree-node');
|
||||
const st = sup.status().services['tree-node'];
|
||||
assert.equal(st.available, 3);
|
||||
assert.equal(st.belowFloor, false);
|
||||
assert.equal(st.instances.length, 3);
|
||||
});
|
||||
|
||||
it('pauses one tree-node and respawns so min available stays 3', async () => {
|
||||
const sup = new Supervisor({ loaded: treeOnly(14700) });
|
||||
supervisors.push(sup);
|
||||
await sup.startService('tree-node');
|
||||
await sup.pauseInstance('tree-node-0');
|
||||
const st = sup.status().services['tree-node'];
|
||||
assert.ok(st.available >= 3, `available ${st.available}`);
|
||||
assert.ok(st.paused >= 1);
|
||||
assert.ok(st.running >= 4);
|
||||
assert.equal(st.belowFloor, false);
|
||||
});
|
||||
|
||||
it('restarts an unhealthy replica and keeps the floor', async () => {
|
||||
const sup = new Supervisor({ loaded: treeOnly(14800) });
|
||||
supervisors.push(sup);
|
||||
await sup.startService('tree-node');
|
||||
const before = sup.instances.get('tree-node-1').pid;
|
||||
await sup.markUnhealthy('tree-node-1');
|
||||
const mon = new Monitor(sup, { intervalMs: 50 });
|
||||
await mon.tick();
|
||||
const rec = sup.instances.get('tree-node-1');
|
||||
assert.ok(rec.pid);
|
||||
assert.notEqual(rec.pid, before);
|
||||
assert.equal(rec.healthy, true);
|
||||
assert.equal(sup.status().services['tree-node'].available, 3);
|
||||
});
|
||||
|
||||
it('stop+replace of a replica keeps min tree-nodes available', async () => {
|
||||
const sup = new Supervisor({ loaded: treeOnly(14900) });
|
||||
supervisors.push(sup);
|
||||
await sup.startService('tree-node');
|
||||
await sup.stopInstance('tree-node-2', { replace: true });
|
||||
const st = sup.status().services['tree-node'];
|
||||
assert.equal(st.available, 3);
|
||||
assert.ok(st.instances.some((i) => i.id === 'tree-node-2' || i.id === 'tree-node-0'));
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue