diff --git a/Overlord-Server/src/wsHandlers.test.ts b/Overlord-Server/src/wsHandlers.test.ts index 0c2fd1f..03de8b0 100644 --- a/Overlord-Server/src/wsHandlers.test.ts +++ b/Overlord-Server/src/wsHandlers.test.ts @@ -69,4 +69,26 @@ describe("wsHandlers ping/pong", () => { handlePong(info, { type: "pong", ts: 3333 } as any); expect(info.lastPingNonce).toBe(2222); }); + + test("handlePong clears matching nonce even when pong is late", () => { + metrics.reset(); + const now = Date.now(); + const info = { + id: "client-4", + role: "client", + ws: { sent: [], send() {} }, + lastSeen: now - 60_000, + online: false, + lastPingSent: now - 20_000, + lastPingNonce: 4444, + } as any; + + handlePong(info, { type: "pong", ts: 4444 } as any); + + expect(info.lastPingNonce).toBeUndefined(); + expect(info.online).toBe(true); + expect(info.lastSeen).toBeGreaterThan(now - 5_000); + const snapshot = metrics.getSnapshot(); + expect(snapshot.ping.count).toBe(0); + }); }); diff --git a/Overlord-Server/src/wsHandlers.ts b/Overlord-Server/src/wsHandlers.ts index 8f7e5d2..e8d2838 100644 --- a/Overlord-Server/src/wsHandlers.ts +++ b/Overlord-Server/src/wsHandlers.ts @@ -128,11 +128,13 @@ export function handlePong(info: ClientInfo, payload: WireMessage) { } const rtt = now - info.lastPingSent; + const nowTs = Date.now(); + + info.lastSeen = nowTs; + info.online = true; + info.lastPingNonce = undefined; if (rtt >= 0 && rtt < maxRttMs) { - const nowTs = Date.now(); - info.lastSeen = nowTs; - info.online = true; info.pingMs = rtt; if (shouldSyncClientToDb(info.id, nowTs)) { upsertClientRow({ @@ -144,8 +146,14 @@ export function handlePong(info: ClientInfo, payload: WireMessage) { } metrics.recordPing(rtt); - info.lastPingNonce = undefined; } else { + if (shouldSyncClientToDb(info.id, nowTs)) { + upsertClientRow({ + id: info.id, + lastSeen: info.lastSeen, + online: 1, + }); + } } }