Add House Party Protocol for fleet-wide queued destruction
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { housePartyTargets, queueHouseParty } from '$lib/server/fleet/house-party.js';
|
||||
import { kick } from '$lib/server/pipeline/worker.js';
|
||||
|
||||
export function GET() {
|
||||
return json({ servers: housePartyTargets() }, { headers: { 'Cache-Control': 'no-store' } });
|
||||
}
|
||||
|
||||
export async function POST({ request }: { request: Request }) {
|
||||
const body = await request.json().catch(() => null);
|
||||
if (!Array.isArray(body?.servers) || !body.servers.every((name: unknown) => typeof name === 'string')) {
|
||||
return json({ error: 'A reviewed server list is required.' }, { status: 400 });
|
||||
}
|
||||
const result = queueHouseParty(body.servers);
|
||||
if (!result.ok) return json(result, { status: 409 });
|
||||
void kick().catch(err => console.error('[house-party] worker kick failed:', err));
|
||||
return json(result, { status: 202 });
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
import DeployServerDialog from '$ui/components/DeployServerDialog.svelte';
|
||||
import BlueprintBuilder from '$ui/components/BlueprintBuilder.svelte';
|
||||
import DeployCollectionDialog from '$ui/components/DeployCollectionDialog.svelte';
|
||||
import HousePartyDialog from '$ui/components/HousePartyDialog.svelte';
|
||||
import type { BlueprintSummary, CollectionSummary } from '$lib/deployment-plan.js';
|
||||
|
||||
interface Deployment {
|
||||
@@ -23,6 +24,8 @@
|
||||
let builderOpen = $state(false);
|
||||
let editingBlueprint = $state<BlueprintSummary | null>(null);
|
||||
let collectionOpen = $state(false);
|
||||
let housePartyOpen = $state(false);
|
||||
let housePartyNotice = $state('');
|
||||
let collections = $state<CollectionSummary[]>([]);
|
||||
let blueprints = $state<BlueprintSummary[]>([]);
|
||||
let blueprintsLoading = $state(true);
|
||||
@@ -92,6 +95,12 @@
|
||||
<DeployServerDialog bind:open onblueprint={loadBlueprints} />
|
||||
<BlueprintBuilder bind:open={builderOpen} blueprint={editingBlueprint} onsaved={blueprintSaved} />
|
||||
<DeployCollectionDialog bind:open={collectionOpen} {blueprintId} />
|
||||
<div class="fleet-shutdown">
|
||||
<div><strong>Call it a night.</strong><p>Queue the whole fleet for removal once each server is empty.</p></div>
|
||||
<Button variant="danger" onclick={() => housePartyOpen = true}>House Party Protocol</Button>
|
||||
</div>
|
||||
<HousePartyDialog bind:open={housePartyOpen} onqueued={count => { housePartyNotice = `Destruction queued for ${count} server${count === 1 ? '' : 's'}. Follow progress in In flight below.`; void load(); }} />
|
||||
{#if housePartyNotice}<p role="status">{housePartyNotice}</p>{/if}
|
||||
<section>
|
||||
<h2>Your blueprints <span>{blueprints.length}</span></h2>
|
||||
{#if blueprintError}<p role="alert" class="error">{blueprintError} <button onclick={loadBlueprints}>Retry</button></p>{/if}
|
||||
@@ -171,6 +180,8 @@
|
||||
{/snippet}
|
||||
|
||||
<style>
|
||||
.fleet-shutdown { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 18px 20px; border: 1px solid var(--border-subtle); border-radius: 12px; }
|
||||
.fleet-shutdown p { margin: 5px 0 0; font-size: 13px; color: var(--text-secondary); }
|
||||
.page { display: flex; flex-direction: column; gap: 28px; }
|
||||
.row-head, .filters, .meta { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
|
||||
.row-head { justify-content: space-between; }
|
||||
|
||||
Reference in New Issue
Block a user