fix: honor Komodo health and prefer fresh telemetry across fleet status
This commit is contained in:
@@ -76,6 +76,9 @@ describe('database fleet and container readiness', () => {
|
||||
await postTelemetry(gameEvent('game_end', 10, 1, 'managed'));
|
||||
rcon.mockResolvedValue(reply(0));
|
||||
await fanoutStatus();
|
||||
expect(getServer('managed')?.game_ended_at).not.toBeNull();
|
||||
await postTelemetry(gameEvent('heartbeat', 0, 0, 'managed'));
|
||||
await fanoutStatus();
|
||||
expect(getServer('managed')).toMatchObject({ game_started_at: null, game_ended_at: null });
|
||||
rcon.mockResolvedValue(reply(1));
|
||||
await fanoutStatus();
|
||||
@@ -118,6 +121,41 @@ describe('database fleet and container readiness', () => {
|
||||
expect(snapshot.serverNow).toBeLessThanOrEqual(Date.now());
|
||||
});
|
||||
|
||||
it('uses telemetry consistently in REST, status events, and metrics without polling RCON', async () => {
|
||||
const { db, inspect, rcon, fanoutStatus } = await setup();
|
||||
const { GET } = await import('../../src/routes/api/servers/+server.js');
|
||||
const { subscribe } = await import('../../src/lib/server/pipeline/bus.js');
|
||||
db.prepare("UPDATE servers SET last_players = 4, last_seen_at = ? WHERE name = 'managed'").run(new Date().toISOString());
|
||||
inspect.mockResolvedValue({ ok: true, state: 'running' });
|
||||
await postTelemetry(gameEvent('heartbeat', 15, 3, 'managed'));
|
||||
const events: unknown[] = [];
|
||||
const unsubscribe = subscribe(event => events.push(event));
|
||||
try { await fanoutStatus(); } finally { unsubscribe(); }
|
||||
expect(rcon).not.toHaveBeenCalled();
|
||||
const server = (await (await GET()).json()).servers[0];
|
||||
expect(server).toMatchObject({ health: 'online', last_players: 3, status_source: 'telemetry', last_error: null,
|
||||
rcon_status: { last_players: 4, last_error: 'timeout:old process' } });
|
||||
expect(server.roster).toHaveLength(3);
|
||||
expect(server.roster[0]).toMatchObject({ ping: null, score: 5000 });
|
||||
expect(events).toContainEqual(expect.objectContaining({ type: 'server-status', entries: [expect.objectContaining({
|
||||
health: 'online', players: 3, roster: server.roster, lastSeenAt: server.last_seen_at
|
||||
})] }));
|
||||
expect(db.prepare("SELECT players FROM metric_samples WHERE server = 'managed'").get()).toEqual({ players: 3 });
|
||||
});
|
||||
|
||||
it('falls back to RCON when telemetry expires and does not renew old reports', async () => {
|
||||
const { db, inspect, rcon, fanoutStatus } = await setup();
|
||||
const { GET } = await import('../../src/routes/api/servers/+server.js');
|
||||
inspect.mockResolvedValue({ ok: true, state: 'running' });
|
||||
await postTelemetry(gameEvent('heartbeat', 15, 3, 'managed'));
|
||||
db.prepare('UPDATE server_telemetry SET received_at = ?').run(new Date(Date.now() - 46_000).toISOString());
|
||||
rcon.mockResolvedValue({ ok: true, endpoint: { host: 'localhost', port: 28960 }, rawReply: 'status',
|
||||
status: { players: 0, map: 'zombie_theater', gametype: 'zom', roster: [] } });
|
||||
await fanoutStatus();
|
||||
expect(rcon).toHaveBeenCalledTimes(1);
|
||||
expect((await (await GET()).json()).servers[0]).toMatchObject({ health: 'online', last_players: 0, status_source: 'rcon' });
|
||||
});
|
||||
|
||||
it('lists registered servers without folders and ignores unregistered folders and tombstones', async () => {
|
||||
const { db } = await setup();
|
||||
const { allServers, listServers } = await import('../../src/lib/server/fleet/servers.js');
|
||||
@@ -151,8 +189,11 @@ describe('database fleet and container readiness', () => {
|
||||
it.each(['unhealthy', 'exited', undefined])('does not poll RCON with container state %s', async (state) => {
|
||||
const { inspect, rcon, fanoutStatus } = await setup();
|
||||
inspect.mockResolvedValue({ ok: false, state, reason: 'not ready' });
|
||||
await postTelemetry(gameEvent('heartbeat', 15, 3, 'managed'));
|
||||
await fanoutStatus();
|
||||
expect(rcon).not.toHaveBeenCalled();
|
||||
const { GET } = await import('../../src/routes/api/servers/+server.js');
|
||||
expect((await (await GET()).json()).servers[0]).toMatchObject({ health: 'offline', last_players: null });
|
||||
});
|
||||
|
||||
it('waits for an EC restart request to settle before trusting the old healthy container', async () => {
|
||||
|
||||
Reference in New Issue
Block a user