Add WS heartbeat every 30s to keep connection alive

This commit is contained in:
Markov 2026-02-26 10:21:33 +01:00
parent a948b2f6fb
commit 92db42113d

View File

@ -9,6 +9,7 @@ class WSClient {
private ws: WebSocket | null = null;
private handlers: Map<string, Set<MessageHandler>> = new Map();
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
private heartbeatTimer: ReturnType<typeof setInterval> | null = null;
private pendingQueue: any[] = [];
private authenticated = false;
private _lobbyId: string | null = null;
@ -38,7 +39,7 @@ class WSClient {
const msg = JSON.parse(event.data);
const type = msg.type;
// Handle auth.ok — flush pending queue
// Handle auth.ok — flush pending queue + start heartbeat
if (type === "auth.ok") {
this._lobbyId = msg.data?.lobby_chat_id || null;
this._projects = msg.data?.projects || [];
@ -49,6 +50,8 @@ class WSClient {
this.ws!.send(JSON.stringify(queued));
}
this.pendingQueue = [];
// Start heartbeat every 30s to keep connection alive
this.startHeartbeat();
}
// Auth error → force re-login
@ -73,6 +76,7 @@ class WSClient {
this.ws.onclose = () => {
this.authenticated = false;
this.stopHeartbeat();
this.reconnectTimer = setTimeout(() => this.connect(), 3000);
};
@ -81,12 +85,27 @@ class WSClient {
disconnect() {
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
this.stopHeartbeat();
this.ws?.close();
this.ws = null;
this.authenticated = false;
this.pendingQueue = [];
}
private startHeartbeat() {
this.stopHeartbeat();
this.heartbeatTimer = setInterval(() => {
this.heartbeat();
}, 30_000);
}
private stopHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
}
}
on(type: string, handler: MessageHandler) {
if (!this.handlers.has(type)) this.handlers.set(type, new Set());
this.handlers.get(type)!.add(handler);