Add House Party Protocol for fleet-wide queued destruction
This commit is contained in:
@@ -416,12 +416,16 @@ async function applyDeploymentTags(deployment: string, gameTagName: string, mapT
|
||||
const destroying = new Set<string>();
|
||||
|
||||
// Persist the request before returning so navigation and client disconnects cannot lose it.
|
||||
export function destroyServer(name: string): DestroyServerResult & { deploymentId?: string } {
|
||||
function hasActiveCreation(name: string): boolean {
|
||||
return !!db().prepare("SELECT 1 FROM server_deployments WHERE server = ? AND action = 'create' AND state IN ('queued', 'running', 'awaiting-health')").get(name);
|
||||
}
|
||||
|
||||
export function destroyServer(name: string, triggeredBy = 'ui'): DestroyServerResult & { deploymentId?: string } {
|
||||
const existing = db().prepare("SELECT id FROM server_deployments WHERE server = ? AND action = 'destroy' AND state IN ('waiting', 'running')").get(name) as { id: string } | undefined;
|
||||
if (existing) return { ok: true, warnings: [], deploymentId: existing.id };
|
||||
if (!getServer(name)) return { ok: false, kind: 'not-found', message: 'Server not found', warnings: [] };
|
||||
if (!getServer(name) && !hasActiveCreation(name)) return { ok: false, kind: 'not-found', message: 'Server not found', warnings: [] };
|
||||
const operation = db().transaction(() => {
|
||||
const id = beginDeployment(name, 'destroy');
|
||||
const id = beginDeployment(name, 'destroy', triggeredBy);
|
||||
db().prepare("UPDATE server_deployments SET state = 'waiting' WHERE id = ?").run(id);
|
||||
deploymentStage(id, 'Waiting to verify the server is empty');
|
||||
return id;
|
||||
@@ -443,6 +447,10 @@ async function runDestructions(): Promise<void> {
|
||||
destroying.add(operation.server);
|
||||
try {
|
||||
if (!getServer(operation.server)) {
|
||||
if (hasActiveCreation(operation.server)) {
|
||||
deploymentStage(operation.id, 'Waiting for server creation to finish');
|
||||
continue;
|
||||
}
|
||||
finishDeployment(operation.id, { ok: false, message: 'Server is no longer registered' });
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { db } from '../db/index.js';
|
||||
import { destroyServer } from './create.js';
|
||||
|
||||
export function housePartyTargets(): string[] {
|
||||
return (db().prepare(`
|
||||
SELECT name FROM servers WHERE destroyed_at IS NULL
|
||||
UNION
|
||||
SELECT server AS name FROM server_deployments
|
||||
WHERE action = 'create' AND state IN ('queued', 'running', 'awaiting-health')
|
||||
ORDER BY name
|
||||
`).all() as { name: string }[]).map(row => row.name);
|
||||
}
|
||||
|
||||
export function queueHouseParty(expectedServers: string[]) {
|
||||
return db().transaction(() => {
|
||||
const servers = housePartyTargets();
|
||||
const expected = [...expectedServers].sort();
|
||||
if (servers.length !== expected.length || servers.some((name, index) => name !== expected[index])) {
|
||||
return { ok: false as const, error: 'The fleet changed. Refresh the preview and review the servers again.' };
|
||||
}
|
||||
const deployments = servers.map(server => {
|
||||
const result = destroyServer(server, 'house-party-protocol');
|
||||
if (!result.ok) throw new Error(result.message);
|
||||
return { server, deploymentId: result.deploymentId! };
|
||||
});
|
||||
return { ok: true as const, deployments };
|
||||
})();
|
||||
}
|
||||
Reference in New Issue
Block a user