Files
electric-cherry/src/lib/ui/fleet-actions.ts
T

59 lines
2.1 KiB
TypeScript

import type { FleetServer } from '../fleet-overview.js';
import type { RuntimeAction } from '../provisioning.js';
import { applicableRuntimeActions } from './lifecycle-actions.js';
export const fleetActions = ['restart', 'start', 'stop', 'rebuild', 'destroy'] as const;
export type FleetAction = RuntimeAction | 'destroy';
export interface FleetActionFailure {
server: string;
error: string;
}
export interface FleetActionResult {
queued: { server: string; deploymentId: string }[];
failed: FleetActionFailure[];
}
export function fleetActionAvailable(
server: FleetServer,
action: FleetAction,
now: number
): boolean {
return action === 'destroy' || applicableRuntimeActions(server, now).includes(action);
}
/** Submit only the reviewed selection. Each server keeps its own durable job and result. */
export async function queueFleetAction(
action: FleetAction,
servers: readonly string[],
request: typeof fetch = fetch
): Promise<FleetActionResult> {
const result: FleetActionResult = { queued: [], failed: [] };
for (const server of new Set(servers)) {
try {
const response =
action === 'destroy'
? await request(`/api/servers/${encodeURIComponent(server)}`, {
method: 'DELETE'
})
: await request('/api/provisioning', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ server, action })
});
const body = await response.json();
if (!response.ok || !body.deploymentId) {
result.failed.push({
server,
error: body.error ?? 'Could not queue this operation.'
});
} else result.queued.push({ server, deploymentId: body.deploymentId });
} catch {
result.failed.push({
server,
error: 'Could not confirm whether the request was queued. Check Provisioning before trying again.'
});
}
}
return result;
}