Show provisioning status during server creation
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { freshStatusTimestamp } from '../../server-freshness.js';
|
||||
export type Health = 'online' | 'stale' | 'offline' | 'starting';
|
||||
export type Health = 'online' | 'stale' | 'offline' | 'starting' | 'provisioning';
|
||||
|
||||
const STALE_MAX_MS = 120_000;
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { db } from '../db/index.js';
|
||||
|
||||
/** Only the latest lifecycle operation can describe the current server. */
|
||||
export function isProvisioning(server: string): boolean {
|
||||
const operation = db().prepare(`SELECT action, state FROM server_deployments
|
||||
WHERE server = ? ORDER BY rowid DESC LIMIT 1`).get(server) as
|
||||
{ action: string; state: string } | undefined;
|
||||
return operation?.action === 'create' && ['queued', 'running', 'awaiting-health'].includes(operation.state);
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { getServer, listServers, setServerField } from '../fleet/servers.js';
|
||||
import { komodoInspectHealthy } from '../integrations/komodo.js';
|
||||
import { restartSettling } from './restart-rollout.js';
|
||||
import { classifyHealth } from '../fleet/health.js';
|
||||
import { isProvisioning } from '../fleet/provisioning.js';
|
||||
import { STATUS_REFRESH_MS } from '../../server-freshness.js';
|
||||
|
||||
const TICK_MS = 15_000;
|
||||
@@ -74,6 +75,18 @@ async function refreshStatus(): Promise<void> {
|
||||
const i = cursor++;
|
||||
if (i >= servers.length) return;
|
||||
const srv = servers[i];
|
||||
// Creation performs its own container, RCON, and map verification.
|
||||
if (isProvisioning(srv.name)) {
|
||||
setServerField(srv.name, 'last_error', null);
|
||||
setServerField(srv.name, 'last_reply_snippet', null);
|
||||
entries[i] = {
|
||||
server: srv.name, players: null, map: srv.map, gametype: null,
|
||||
roster: null, health: 'provisioning', lastSeenAt: srv.last_seen_at,
|
||||
lastError: null, endpoint: null, reason: null, replySnippet: null,
|
||||
activeSince: null, inactiveSince: null, gameStartedAt: null, gameEndedAt: null
|
||||
};
|
||||
continue;
|
||||
}
|
||||
const container = restartSettling(srv.name)
|
||||
? { ok: false as const, state: 'restarting', reason: 'Restart requested' }
|
||||
: await komodoInspectHealthy(srv.name).catch((err) => ({
|
||||
|
||||
@@ -107,7 +107,9 @@
|
||||
<StatusPip {health} />
|
||||
<strong class="name"><ServerIdentity {name} mapLabel={mapLabelOverride} /></strong>
|
||||
</div>
|
||||
{#if health === 'starting'}
|
||||
{#if health === 'provisioning'}
|
||||
<Badge variant="info" uppercase>Provisioning</Badge>
|
||||
{:else if health === 'starting'}
|
||||
<Badge variant="info" uppercase>Starting</Badge>
|
||||
{:else if health === 'offline'}
|
||||
<Badge variant="danger" uppercase>offline</Badge>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
background: var(--spark-500);
|
||||
animation: electric-pulse 1.6s ease-in-out infinite;
|
||||
}
|
||||
.dot-stale, .dot-starting {
|
||||
.dot-stale, .dot-starting, .dot-provisioning {
|
||||
background: var(--amber-500);
|
||||
box-shadow: var(--amber-glow);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
let toneClass = $derived(
|
||||
health === 'online' ? 't-online' :
|
||||
health === 'stale' || health === 'starting' ? 't-warning' :
|
||||
health === 'stale' || health === 'starting' || health === 'provisioning' ? 't-warning' :
|
||||
't-danger'
|
||||
);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
label ?? (
|
||||
health === 'online' ? 'online' :
|
||||
health === 'starting' ? 'starting' :
|
||||
health === 'provisioning' ? 'provisioning' :
|
||||
health === 'stale' ? 'stale' :
|
||||
'offline'
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export type StatusTone = 'neutral' | 'online' | 'warning' | 'danger' | 'info';
|
||||
const states: Record<string, [string, StatusTone]> = {
|
||||
provisioning: ['Provisioning', 'info'],
|
||||
online: ['Online', 'online'], offline: ['Offline', 'danger'], stale: ['Report outdated', 'warning'], starting: ['Starting', 'info'],
|
||||
queued: ['Queued', 'neutral'], pending: ['Queued for restart', 'neutral'], running: ['In progress', 'info'], active: ['In progress', 'info'],
|
||||
deploying: ['Installing files', 'info'], restarting: ['Restarting', 'info'],
|
||||
|
||||
@@ -13,7 +13,7 @@ export interface RosterPlayer {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type Health = 'online' | 'stale' | 'offline' | 'starting';
|
||||
export type Health = 'online' | 'stale' | 'offline' | 'starting' | 'provisioning';
|
||||
export type RconFailure = 'no-config' | 'no-port' | 'send-error' | 'timeout' | 'bad-reply' | 'no-players';
|
||||
|
||||
export interface RconEndpoint {
|
||||
|
||||
Reference in New Issue
Block a user