Supplement telemetry rosters with fresh RCON pings

This commit is contained in:
2026-10-06 21:13:02 -04:00
parent 675d9b1576
commit 1b42244858
6 changed files with 125 additions and 14 deletions
+55
View File
@@ -47,6 +47,61 @@ describe('shared server observation', () => {
expect(selected.rcon_status).toBe(raw);
});
it('supplements telemetry members with GUID-matched pings without changing scores or names', () => {
const telemetry = report();
const raw = server({ roster: [
{ ...telemetry.players[1], num: 2, score: 10, ping: 0, name: 'Old name' },
{ ...telemetry.players[0], num: 3, score: 20, ping: 999 },
{ ...telemetry.players[2], num: 4, score: 30, ping: 45, guid: 'different-player' }
] });
const selected = selectServerObservation(server({ rcon_status: raw }), telemetry, now);
expect(selected.roster).toEqual(telemetry.players.map((player, i) => ({
name: player.name, guid: player.guid, num: null, score: 5000, ping: [999, 0, null][i]
})));
expect(selected.last_players).toBe(3);
expect(selected.rcon_status).toBe(raw);
// A new telemetry report must not renew the RCON sample's age.
const expired = selectServerObservation({ ...selected, container_checked_at: at(90_001) }, report(90_001), now + 90_001);
expect(expired.health).toBe('online');
expect(expired.roster?.map(player => player.ping)).toEqual([null, null, null]);
});
it('prefers telemetry ping, including zero, and fills absent or null readings from RCON', () => {
const telemetry = report();
telemetry.players[0].ping = 0;
telemetry.players[1].ping = null;
const raw = server({ roster: telemetry.players.map(player => ({ ...player, num: 0, score: 10, ping: 42 })) });
expect(selectServerObservation(server({ rcon_status: raw }), telemetry, now).roster?.map(player => player.ping)).toEqual([0, 42, 42]);
});
it.each([
{ last_seen_at: at(-90_001) }, { last_seen_at: at(2000) }, { last_seen_at: null },
{ last_error: 'timeout', rcon_failures: 2 }, { last_map: 'other-map' }
])('does not supplement pings from unusable RCON evidence: %j', changes => {
const telemetry = report();
const raw = server({ ...changes, roster: [{ ...telemetry.players[0], num: 0, score: 100, ping: 42 }] });
expect(selectServerObservation(server({ rcon_status: raw }), telemetry, now).roster?.[0].ping).toBeNull();
});
it('requires RCON samples after the latest lifecycle and tolerates one transient failure', () => {
const telemetry = report();
const raw = server({ last_seen_at: at(-90_000), roster: [{ ...telemetry.players[0], num: 0, score: 100, ping: 42 }] });
expect(selectServerObservation(server({ rcon_status: raw }), telemetry, now).roster?.[0].ping).toBe(42);
expect(selectServerObservation(server({ rcon_status: raw, telemetry_after: at(-90_000) }), telemetry, now).roster?.[0].ping).toBeNull();
expect(selectServerObservation(server({ rcon_status: { ...raw, last_error: 'timeout', rcon_failures: 1 } }), telemetry, now).roster?.[0].ping).toBe(42);
});
it.each(['duplicate', 'missing-guid', 'null', 'negative', 'invalid'])('rejects %s ping matches', mode => {
const telemetry = report();
const player = { ...telemetry.players[0], num: 0, score: 100, ping: 42 as number | null, guid: telemetry.players[0].guid as string | null };
if (mode === 'missing-guid') player.guid = null;
if (mode === 'null') player.ping = null;
if (mode === 'negative') player.ping = -1;
if (mode === 'invalid') player.ping = NaN;
const raw = server({ roster: mode === 'duplicate' ? [player, { ...player, ping: 50 }] : [player] });
expect(selectServerObservation(server({ rcon_status: raw }), telemetry, now).roster?.[0].ping).toBeNull();
});
it('uses the latest HTTP or streamed telemetry and falls back without extending freshness', () => {
const original = server();
const selected = selectServerObservation(server({ rcon_status: original, telemetry: report(0, 2) }), report(-1000), now);