Add Plutonium version checks and scheduled rolling restarts

This commit is contained in:
2026-09-21 18:47:24 -04:00
parent 424d6cefb6
commit 47d6dc07b7
10 changed files with 583 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
export interface MaintenanceSchedule {
enabled: boolean;
time: string;
nextAt: string | null;
}
export interface PlutoniumRelease {
revision: number | null;
checkedAt: string | null;
error: string | null;
}
export interface PlutoniumVersion {
server: string;
revision: number | null;
checked_at: string | null;
error: string | null;
}
export interface MaintenanceJob {
id: number;
server: string;
state: 'queued' | 'restarting' | 'done' | 'failed' | 'cancelled';
target_revision: number | null;
requested_at: string;
restarted_at: string | null;
finished_at: string | null;
detail: string | null;
}
export interface PlutoniumStatus {
release: PlutoniumRelease;
schedule: MaintenanceSchedule;
servers: PlutoniumVersion[];
jobs: MaintenanceJob[];
}
/** Accept explicit revision tokens only, never engine versions or build dates. */
export function parsePlutoniumRevision(text: string): number | null {
const match = text.replace(/\^[0-9]/g, '').match(/\br([1-9]\d{2,8})\b/i);
return match ? Number(match[1]) : null;
}
export function parseChangelogRevision(html: string): number {
const headings = [...html.matchAll(/<h2\b[^>]*>([\s\S]*?)<\/h2>/gi)];
const revisions = headings.map(h => parsePlutoniumRevision(h[1].replace(/<[^>]*>/g, ' ')))
.filter((r): r is number => r !== null);
if (!revisions.length) throw new Error('The Plutonium changelog did not contain a release heading.');
return Math.max(...revisions);
}
export function nextMaintenanceAt(time: string, now = new Date()): string {
if (!/^([01]\d|2[0-3]):[0-5]\d$/.test(time)) throw new Error('Choose a valid UTC time (HH:mm).');
const next = new Date(now);
const [hour, minute] = time.split(':').map(Number);
next.setUTCHours(hour, minute, 0, 0);
if (next <= now) next.setUTCDate(next.getUTCDate() + 1);
return next.toISOString();
}