fix: honor Komodo health and prefer fresh telemetry across fleet status
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { selectServerObservation } from '$lib/server-observation.js';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import { browser } from '$app/environment';
|
||||
import { statusByServer, statusReceivedAt, syncServerTime, matchEventsByServer } from './servers.js';
|
||||
import { statusByServer, statusReceivedAt, syncServerTime, matchEventsByServer, telemetryByServer, uiNow } from './servers.js';
|
||||
import { type FleetServer, type FleetOperation } from '$lib/fleet-overview.js';
|
||||
|
||||
export const fleet = writable<{ servers: FleetServer[]; operations: FleetOperation[]; receivedAt: number }>({
|
||||
@@ -10,18 +11,24 @@ export const fleetError = writable('');
|
||||
export const fleetRefreshing = writable(false);
|
||||
export const fleetIntegrations = writable<{ rcon: boolean; komodo: boolean; rconTimeoutMs: number; defaultRconHost: string } | null>(null);
|
||||
|
||||
export const fleetServers = derived([fleet, statusByServer, statusReceivedAt, matchEventsByServer], ([snapshot, live, received, matches]) =>
|
||||
export const fleetServers = derived([fleet, statusByServer, statusReceivedAt, matchEventsByServer, telemetryByServer, uiNow], ([snapshot, live, received, matches, reports, now]) =>
|
||||
snapshot.servers.map(server => {
|
||||
const status = received > snapshot.receivedAt ? live.get(server.name) : undefined;
|
||||
const current = status ? { ...server, last_players: status.players, last_map: status.map,
|
||||
const base = status ? { ...server, last_players: status.players, last_map: status.map,
|
||||
last_gametype: status.gametype, last_seen_at: status.lastSeenAt, last_error: status.lastError,
|
||||
roster: status.roster, health: status.health, endpoint: status.endpoint, replySnippet: status.replySnippet, active_since: status.activeSince,
|
||||
inactive_since: status.inactiveSince, game_started_at: status.gameStartedAt,
|
||||
game_ended_at: status.gameEndedAt } : server;
|
||||
game_ended_at: status.gameEndedAt, container_state: status.containerState ?? server.container_state,
|
||||
container_checked_at: status.containerCheckedAt ?? server.container_checked_at,
|
||||
telemetry_after: status.telemetryAfter ?? server.telemetry_after, rcon_status: status.rconStatus,
|
||||
telemetry: status.telemetry ?? server.telemetry } : server;
|
||||
const current = selectServerObservation(base, reports.get(server.name), now);
|
||||
const match = matches.get(server.name);
|
||||
// Apply lifecycle events immediately, until a newer status observes them
|
||||
// or confirms that the lobby has emptied.
|
||||
if (!match || Date.parse(match.receivedAt) <= Date.parse(current.last_seen_at ?? '')
|
||||
if (!match || current.health !== 'online'
|
||||
|| (current.telemetry_after && Date.parse(match.receivedAt) <= Date.parse(current.telemetry_after))
|
||||
|| Date.parse(match.receivedAt) <= Date.parse(current.last_seen_at ?? '')
|
||||
|| match.receivedAt < (current.game_started_at ?? '')
|
||||
|| match.receivedAt < (current.game_ended_at ?? '')) return current;
|
||||
return { ...current, game_started_at: match.event === 'game_start' ? match.receivedAt : current.game_started_at,
|
||||
|
||||
@@ -5,13 +5,8 @@ import type { GameTelemetry } from '$lib/telemetry.js';
|
||||
export const telemetryByServer = writable<Map<string, GameTelemetry>>(new Map());
|
||||
export const matchEventsByServer = writable<Map<string, GameTelemetry>>(new Map());
|
||||
|
||||
export interface RosterPlayer {
|
||||
num: number | null;
|
||||
score: number;
|
||||
ping: number;
|
||||
guid: string | null;
|
||||
name: string;
|
||||
}
|
||||
export type { StatusPlayer as RosterPlayer } from '$lib/server-observation.js';
|
||||
import type { StatusPlayer as RosterPlayer, GameObservation } from '$lib/server-observation.js';
|
||||
|
||||
export type Health = 'online' | 'stale' | 'offline' | 'starting' | 'provisioning';
|
||||
export type RconFailure = 'no-config' | 'no-port' | 'send-error' | 'timeout' | 'bad-reply' | 'no-players';
|
||||
@@ -23,6 +18,11 @@ export interface RconEndpoint {
|
||||
|
||||
export interface ServerStatus {
|
||||
server: string;
|
||||
containerState?: string | null;
|
||||
containerCheckedAt?: string | null;
|
||||
telemetryAfter?: string | null;
|
||||
rconStatus?: GameObservation;
|
||||
telemetry?: GameTelemetry;
|
||||
players: number | null;
|
||||
map: string | null;
|
||||
gametype: string | null;
|
||||
|
||||
Reference in New Issue
Block a user