refactor: make provisioning own instance lifecycle operations

This commit is contained in:
2026-09-27 14:45:00 -04:00
parent cfed584614
commit df265d1900
44 changed files with 1791 additions and 1609 deletions
@@ -2,6 +2,7 @@ import { json } from '@sveltejs/kit';
import { db } from '$lib/server/db/index.js';
import { emit, type BetaStage } from '$lib/server/pipeline/bus.js';
import { storedPlan } from '$lib/server/fleet/beta-tests.js';
import { releaseRestartRequest } from '$lib/server/provisioning/index.js';
function parseId(raw: string): number | null {
const n = Number.parseInt(raw, 10);
@@ -28,6 +29,7 @@ export async function POST({ params, request }: { params: { id: string }; reques
// Best-effort resume point: if we already got past restart, go back to
// health check; otherwise back to waiting for the server to be empty.
const nextStage: BetaStage = row.restarted_at ? 'awaiting-health' : 'awaiting-empty';
if (!row.restarted_at) releaseRestartRequest(body.server, { kind: 'beta', id: String(betaId) });
const now = new Date().toISOString();
db()
.prepare('UPDATE beta_servers SET stage = ?, error = NULL, updated_at = ? WHERE beta_id = ? AND server = ?')
@@ -1,4 +1,5 @@
import { json } from '@sveltejs/kit';
import { releaseRestartRequest } from '$lib/server/provisioning/index.js';
import { db } from '$lib/server/db/index.js';
import { getBeta } from '$lib/server/fleet/beta.js';
import { activity, currentRun, evidence, readMetrics, saveMetrics, setOutcome, storedPlan } from '$lib/server/fleet/beta-tests.js';
@@ -50,6 +51,8 @@ export async function POST({ params, request }: { params: { id: string }; reques
if (stored.outcome === 'inconclusive') throw new Error('The testing window ended. Roll back and open a new beta with a longer deadline');
if (db().prepare("SELECT 1 FROM beta_servers WHERE beta_id = ? AND error LIKE 'deploy:%'").get(id)) throw new Error('Deployment was incomplete. Roll back before opening a fresh beta');
db().transaction(() => {
const servers = db().prepare('SELECT server FROM beta_servers WHERE beta_id = ?').all(id) as { server: string }[];
for (const { server } of servers) releaseRestartRequest(server, { kind: 'beta', id: String(id) });
db().prepare('UPDATE beta_test_runs SET retired_at = ? WHERE beta_id = ? AND retired_at IS NULL').run(new Date().toISOString(), id);
db().prepare("UPDATE beta_servers SET stage = 'awaiting-empty', error = NULL, restarted_at = NULL, healthy_at = NULL WHERE beta_id = ? AND deployed_at IS NOT NULL AND error NOT LIKE 'deploy:%'").run(id);
// SQL NULL does not satisfy NOT LIKE.
+1 -1
View File
@@ -1,3 +1,3 @@
import { json } from '@sveltejs/kit';
import { listDeployments } from '$lib/server/fleet/deployments.js';
import { listDeployments } from '$lib/server/provisioning/index.js';
export function GET() { return json({ deployments: listDeployments() }); }
+1 -1
View File
@@ -1,6 +1,6 @@
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/db/index.js';
import { getDeployment } from '$lib/server/fleet/deployments.js';
import { getDeployment } from '$lib/server/provisioning/index.js';
export async function GET({ params }: { params: { id: string } }) {
const lifecycle = getDeployment(params.id);
@@ -1,5 +1,5 @@
import { json } from '@sveltejs/kit';
import { cancelRemoval } from '$lib/server/fleet/deployments.js';
import { cancelRemoval } from '$lib/server/provisioning/index.js';
export function POST({ params }: { params: { id: string } }) {
if (!cancelRemoval(params.id)) return json({ error: 'Removal has already begun or this request is no longer waiting. Refresh to see its current state.' }, { status: 409 });
@@ -1,5 +1,5 @@
import { json } from '@sveltejs/kit';
import { resumeVerification, resumeCleanup, resumeRebuild } from '$lib/server/fleet/deployments.js';
import { resumeVerification, resumeCleanup, resumeRebuild } from '$lib/server/provisioning/index.js';
import { kick } from '$lib/server/pipeline/worker.js';
export function POST({ params }: { params: { id: string } }) {
@@ -1,5 +1,5 @@
import { json } from '@sveltejs/kit';
import { previewCreation } from '$lib/server/fleet/create.js';
import { previewCreation } from '$lib/server/provisioning/index.js';
export async function POST({ request }: { request: Request }) {
try {
+2 -2
View File
@@ -1,6 +1,6 @@
import { json } from '@sveltejs/kit';
import { listDeployments } from '$lib/server/fleet/deployments.js';
import { requestLifecycle } from '$lib/server/fleet/lifecycle.js';
import { listDeployments } from '$lib/server/provisioning/index.js';
import { requestLifecycle } from '$lib/server/provisioning/index.js';
import { runtimeActions, type RuntimeAction } from '$lib/provisioning.js';
import { kick } from '$lib/server/pipeline/worker.js';
+1 -1
View File
@@ -4,7 +4,7 @@ import { json } from '@sveltejs/kit';
import { listServers, heldByBeta } from '$lib/server/fleet/servers.js';
import { classifyHealth } from '$lib/server/fleet/health.js';
import { isProvisioning } from '$lib/server/fleet/provisioning.js';
import { queueCreateServer } from '$lib/server/fleet/create.js';
import { queueCreateServer } from '$lib/server/provisioning/index.js';
import { config, komodoConfigured, rconConfigured } from '$lib/server/config.js';
import type { RconPlayer } from '$lib/server/integrations/rcon.js';
import type { GameMode, ZombieGame } from '$lib/server/fleet/map-aliases.js';
+1 -1
View File
@@ -1,6 +1,6 @@
import { kick } from '$lib/server/pipeline/worker.js';
import { json } from '@sveltejs/kit';
import { destroyServer } from '$lib/server/fleet/create.js';
import { destroyServer } from '$lib/server/provisioning/index.js';
export async function DELETE({ params }: { params: { name: string } }) {
const name = params.name;