Pool Plutonium keys by game for launches and autoscaling
This commit is contained in:
@@ -90,19 +90,36 @@ describe('multi-server blueprints', () => {
|
||||
|
||||
describe('atomic collection launches', () => {
|
||||
|
||||
it('counts available keys once per game across all maps without reserving them in a preview', async () => {
|
||||
const { blueprint } = await previewLineup();
|
||||
const { saveServerKey, reserveServerKey } = await import('../../src/lib/server/fleet/server-keys.js');
|
||||
const { previewCollection, queueCollection } = await import('../../src/lib/server/fleet/collections.js');
|
||||
const { db } = await import('../../src/lib/server/db/index.js');
|
||||
saveServerKey('t5', 'pool-one'); saveServerKey('t5', 'pool-two'); saveServerKey('t6', 'pool-three');
|
||||
const preview = previewCollection(blueprint.id);
|
||||
expect(preview.servers.map(server => server.hasSavedKey)).toEqual([true, true, false, true, false]);
|
||||
expect(db().prepare('SELECT * FROM server_key_leases').all()).toEqual([]);
|
||||
reserveServerKey('t5_zombie_pentagon_1', 't5');
|
||||
expect(() => queueCollection({ previewId: preview.id })).toThrow(/No available T5 server keys/);
|
||||
expect(db().prepare('SELECT * FROM server_creation_jobs').all()).toEqual([]);
|
||||
expect(db().prepare('SELECT * FROM server_key_leases').all()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('rolls back all earlier jobs and key changes if the final server has no valid key', async () => {
|
||||
const { preview } = await previewLineup();
|
||||
const { queueCollection } = await import('../../src/lib/server/fleet/collections.js');
|
||||
const { db } = await import('../../src/lib/server/db/index.js');
|
||||
const { saveServerKey, getServerKey } = await import('../../src/lib/server/fleet/server-keys.js');
|
||||
saveServerKey(preview.servers[0].name!, 'original-key');
|
||||
saveServerKey('t5', 'original-key');
|
||||
const keys = keysFor(preview);
|
||||
delete keys[preview.servers[4].name!];
|
||||
expect(() => queueCollection({ previewId: preview.id, keys })).toThrow(/Save a Plutonium server key/);
|
||||
expect(() => queueCollection({ previewId: preview.id, keys })).toThrow(/No available .* server keys/);
|
||||
for (const table of ['server_launch_collections', 'server_collection_members', 'server_creation_jobs', 'server_deployments', 'server_launch_previews', 'server_launch_recipes']) {
|
||||
expect(db().prepare(`SELECT * FROM ${table}`).all()).toEqual([]);
|
||||
}
|
||||
expect(getServerKey(preview.servers[0].name!)).toBe('original-key');
|
||||
expect(getServerKey(preview.servers[0].name!)).toBeUndefined();
|
||||
expect(db().prepare('SELECT pluto_key FROM server_keys').get()).toEqual({ pluto_key: 'original-key' });
|
||||
expect(db().prepare('SELECT * FROM server_key_leases').all()).toEqual([]);
|
||||
expect(db().prepare('SELECT * FROM server_keys').all()).toHaveLength(1);
|
||||
keys[preview.servers[4].name!] = 'invalid key';
|
||||
expect(() => queueCollection({ previewId: preview.id, keys })).toThrow(/without whitespace/);
|
||||
@@ -115,7 +132,7 @@ describe('atomic collection launches', () => {
|
||||
const { queueCollection, previewCollection, getCollection } = await import('../../src/lib/server/fleet/collections.js');
|
||||
const { saveServerKey } = await import('../../src/lib/server/fleet/server-keys.js');
|
||||
const { db, closeDb } = await import('../../src/lib/server/db/index.js');
|
||||
for (const server of preview.servers) saveServerKey(server.name!, `saved-${server.name}`);
|
||||
for (const server of preview.servers) saveServerKey(server.name!.slice(0, 2), `saved-${server.name}`);
|
||||
const ready = previewCollection(blueprint.id);
|
||||
expect(ready.servers.every(server => server.hasSavedKey)).toBe(true);
|
||||
const queued = queueCollection({ previewId: ready.id });
|
||||
@@ -171,17 +188,18 @@ describe('matching a blueprint exactly', () => {
|
||||
expect(db().prepare('SELECT state FROM server_deployments WHERE id = ?').get(first.deploymentId)).toEqual({ state: 'queued' });
|
||||
expect(getCollection(queued.collectionId!)?.collection).toMatchObject({ done: 1, total: 1, active: 0 });
|
||||
const { getServerKey } = await import('../../src/lib/server/fleet/server-keys.js');
|
||||
expect(getServerKey(second.name)).toBe('second');
|
||||
expect(getServerKey(second.name)).toBeUndefined();
|
||||
expect(db().prepare("SELECT pluto_key FROM server_keys WHERE pluto_key='second'").get()).toEqual({ pluto_key: 'second' });
|
||||
});
|
||||
|
||||
it('rolls back removals and creation cancellations when a required key is missing', async () => {
|
||||
it('rolls back removals and creation cancellations when the game pool is exhausted', async () => {
|
||||
const { queueCreateServer } = await import('../../src/lib/server/fleet/create.js');
|
||||
const old = queueCreateServer({ gameMode: 'zombie', mapSlug: 'moon', plutoKey: 'existing' });
|
||||
if (!old.ok) throw new Error(old.message);
|
||||
const plan = await blueprint([{ game: 't5', mapSlug: 'theater', count: 1 }]);
|
||||
const plan = await blueprint([{ game: 't5', mapSlug: 'theater', count: 2 }]);
|
||||
const { previewCollection, queueCollection } = await import('../../src/lib/server/fleet/collections.js');
|
||||
const preview = previewCollection(plan.id, 'exact');
|
||||
expect(() => queueCollection({ previewId: preview.id })).toThrow(/Save a Plutonium server key/);
|
||||
expect(() => queueCollection({ previewId: preview.id })).toThrow(/No available .* server keys/);
|
||||
const { db } = await import('../../src/lib/server/db/index.js');
|
||||
expect(db().prepare('SELECT state FROM server_deployments WHERE id = ?').get(old.deploymentId)).toEqual({ state: 'queued' });
|
||||
for (const table of ['server_collection_removals', 'server_launch_collections', 'server_creation_dependencies']) expect(db().prepare(`SELECT * FROM ${table}`).all()).toEqual([]);
|
||||
|
||||
Reference in New Issue
Block a user