fix: queue WS messages until auth.ok, flush on connect
All checks were successful
Deploy Web Client / deploy (push) Successful in 2m6s

This commit is contained in:
Markov 2026-02-23 19:08:38 +01:00
parent 4abca2a793
commit 02b426a013

View File

@ -9,6 +9,8 @@ class WSClient {
private ws: WebSocket | null = null; private ws: WebSocket | null = null;
private handlers: Map<string, Set<MessageHandler>> = new Map(); private handlers: Map<string, Set<MessageHandler>> = new Map();
private reconnectTimer: ReturnType<typeof setTimeout> | null = null; private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
private pendingQueue: any[] = [];
private authenticated = false;
private _lobbyId: string | null = null; private _lobbyId: string | null = null;
private _projects: Array<{ id: string; slug: string; name: string }> = []; private _projects: Array<{ id: string; slug: string; name: string }> = [];
private _online: string[] = []; private _online: string[] = [];
@ -27,6 +29,8 @@ class WSClient {
console.error("NEXT_PUBLIC_WS_URL is not set!"); console.error("NEXT_PUBLIC_WS_URL is not set!");
return; return;
} }
this.authenticated = false;
this.ws = new WebSocket(`${wsBase}/ws?token=${token}`); this.ws = new WebSocket(`${wsBase}/ws?token=${token}`);
this.ws.onmessage = (event) => { this.ws.onmessage = (event) => {
@ -34,11 +38,17 @@ class WSClient {
const msg = JSON.parse(event.data); const msg = JSON.parse(event.data);
const type = msg.type; const type = msg.type;
// Handle auth.ok // Handle auth.ok — flush pending queue
if (type === "auth.ok") { if (type === "auth.ok") {
this._lobbyId = msg.data?.lobby_chat_id || null; this._lobbyId = msg.data?.lobby_chat_id || null;
this._projects = msg.data?.projects || []; this._projects = msg.data?.projects || [];
this._online = msg.data?.online || []; this._online = msg.data?.online || [];
this.authenticated = true;
// Flush queued messages
for (const queued of this.pendingQueue) {
this.ws!.send(JSON.stringify(queued));
}
this.pendingQueue = [];
} }
// Dispatch to handlers // Dispatch to handlers
@ -54,6 +64,7 @@ class WSClient {
}; };
this.ws.onclose = () => { this.ws.onclose = () => {
this.authenticated = false;
this.reconnectTimer = setTimeout(() => this.connect(), 3000); this.reconnectTimer = setTimeout(() => this.connect(), 3000);
}; };
@ -64,6 +75,8 @@ class WSClient {
if (this.reconnectTimer) clearTimeout(this.reconnectTimer); if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
this.ws?.close(); this.ws?.close();
this.ws = null; this.ws = null;
this.authenticated = false;
this.pendingQueue = [];
} }
on(type: string, handler: MessageHandler) { on(type: string, handler: MessageHandler) {
@ -73,8 +86,11 @@ class WSClient {
} }
send(data: any) { send(data: any) {
if (this.ws?.readyState === WebSocket.OPEN) { if (this.ws?.readyState === WebSocket.OPEN && this.authenticated) {
this.ws.send(JSON.stringify(data)); this.ws.send(JSON.stringify(data));
} else {
// Queue until connected + authenticated
this.pendingQueue.push(data);
} }
} }