refactor: make provisioning own instance lifecycle operations
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
import { db } from '../db/index.js';
|
||||
import { emit } from './bus.js';
|
||||
import type { BetaStage } from './bus.js';
|
||||
import { komodoConfigured, rconConfigured } from '../config.js';
|
||||
import { rconGetPlayerCount } from '../integrations/rcon.js';
|
||||
import { refreshRestartRollout, restartInRollout, rolloutHealth, rolloutWaitReason } from './restart-rollout.js';
|
||||
import { requestRestart } from '../provisioning/index.js';
|
||||
import { plannedBetaTick } from './beta-plan-runner.js';
|
||||
|
||||
interface BetaServerActiveRow {
|
||||
@@ -20,10 +18,6 @@ function nowIso(): string {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
|
||||
function integrationsOn(): boolean {
|
||||
return komodoConfigured() && rconConfigured();
|
||||
}
|
||||
|
||||
const setStage = () =>
|
||||
db().prepare(
|
||||
`UPDATE beta_servers
|
||||
@@ -94,9 +88,7 @@ export function betaTick(): Promise<{ processed: number }> {
|
||||
}
|
||||
|
||||
async function runBetaTick(): Promise<{ processed: number }> {
|
||||
if (integrationsOn()) await refreshRestartRollout();
|
||||
await plannedBetaTick();
|
||||
if (!integrationsOn()) return { processed: 0 };
|
||||
|
||||
const rows = db()
|
||||
.prepare(
|
||||
@@ -131,49 +123,21 @@ async function runBetaTick(): Promise<{ processed: number }> {
|
||||
async function advance(row: BetaServerActiveRow): Promise<void> {
|
||||
switch (row.stage) {
|
||||
case 'awaiting-empty':
|
||||
case 'restarting': {
|
||||
const waitReason = rolloutWaitReason(row.server);
|
||||
if (waitReason) {
|
||||
transition(row.beta_id, row.server, 'awaiting-empty', waitReason);
|
||||
return;
|
||||
}
|
||||
const players = await rconGetPlayerCount(row.server);
|
||||
if (players === null) return; // hold — RCON unreachable, try next tick
|
||||
if (players > 0) return; // hold — still populated
|
||||
transition(row.beta_id, row.server, 'restarting');
|
||||
const r = await restartInRollout(row.server);
|
||||
if (r.kind === 'queued') {
|
||||
transition(row.beta_id, row.server, 'awaiting-empty', r.message);
|
||||
return;
|
||||
}
|
||||
if (r.kind === 'failed') {
|
||||
transition(row.beta_id, row.server, 'failed', r.message);
|
||||
return;
|
||||
}
|
||||
const next = row.wait_for_health ? 'awaiting-health' : row.wait_for_match ? 'awaiting-match' : 'ready';
|
||||
transition(row.beta_id, row.server, next);
|
||||
return;
|
||||
}
|
||||
case 'restarting':
|
||||
case 'awaiting-health': {
|
||||
const h = rolloutHealth(row.server);
|
||||
if (!h.ok) {
|
||||
// Record the failure reason (including any snippet) so the
|
||||
// beta detail UI can surface why we're stuck.
|
||||
setStage().run(
|
||||
'awaiting-health',
|
||||
h.reason,
|
||||
nowIso(),
|
||||
'awaiting-health',
|
||||
'awaiting-health',
|
||||
nowIso(),
|
||||
'awaiting-health',
|
||||
'awaiting-health',
|
||||
nowIso(),
|
||||
'awaiting-health',
|
||||
nowIso(),
|
||||
row.beta_id,
|
||||
row.server
|
||||
);
|
||||
const operation = requestRestart(row.server, { kind: 'beta', id: String(row.beta_id) });
|
||||
if (['failed','interrupted','cancelled'].includes(operation.state)) {
|
||||
transition(row.beta_id, row.server, 'failed', operation.error ?? operation.stage);
|
||||
return;
|
||||
}
|
||||
if (!operation.submitted_at || operation.state === 'running') {
|
||||
transition(row.beta_id, row.server, 'awaiting-empty', operation.stage);
|
||||
return;
|
||||
}
|
||||
db().prepare('UPDATE beta_servers SET restarted_at = ? WHERE beta_id = ? AND server = ?')
|
||||
.run(operation.submitted_at, row.beta_id, row.server);
|
||||
if (row.wait_for_health && operation.state !== 'done') {
|
||||
transition(row.beta_id, row.server, 'awaiting-health', operation.stage);
|
||||
return;
|
||||
}
|
||||
const next = row.wait_for_match ? 'awaiting-match' : 'ready';
|
||||
|
||||
Reference in New Issue
Block a user