← back to Dw War Room
src/data/WebSocketClient.ts
76 lines
// ═══════════════════════════════════════════════
// DW War Room 3D — Dual WebSocket Client
// Connects to both Governance and Boardroom WS servers
// ═══════════════════════════════════════════════
import type { WSEvent } from '../types';
type EventHandler = (event: WSEvent, source: 'governance' | 'boardroom') => void;
export class DualWebSocketClient {
private govWs: WebSocket | null = null;
private brWs: WebSocket | null = null;
private handlers: EventHandler[] = [];
private reconnectTimers: { gov?: number; br?: number } = {};
constructor(
private govUrl: string = import.meta.env.VITE_GOVERNANCE_WS || 'ws://45.61.58.125:4020/ws',
private brUrl: string = import.meta.env.VITE_BOARDROOM_WS || 'ws://45.61.58.125:4040/ws'
) {}
onEvent(handler: EventHandler): void {
this.handlers.push(handler);
}
connect(): void {
this.connectGov();
this.connectBr();
}
disconnect(): void {
if (this.govWs) this.govWs.close();
if (this.brWs) this.brWs.close();
if (this.reconnectTimers.gov) clearTimeout(this.reconnectTimers.gov);
if (this.reconnectTimers.br) clearTimeout(this.reconnectTimers.br);
}
private connectGov(): void {
try {
this.govWs = new WebSocket(this.govUrl);
this.govWs.onmessage = (evt) => this.dispatch(evt.data, 'governance');
this.govWs.onclose = () => {
this.reconnectTimers.gov = window.setTimeout(() => this.connectGov(), 5000);
};
this.govWs.onerror = () => this.govWs?.close();
} catch {}
}
private connectBr(): void {
try {
this.brWs = new WebSocket(this.brUrl);
this.brWs.onmessage = (evt) => this.dispatch(evt.data, 'boardroom');
this.brWs.onclose = () => {
this.reconnectTimers.br = window.setTimeout(() => this.connectBr(), 5000);
};
this.brWs.onerror = () => this.brWs?.close();
} catch {}
}
private dispatch(data: string, source: 'governance' | 'boardroom'): void {
try {
const event: WSEvent = JSON.parse(data);
for (const handler of this.handlers) {
handler(event, source);
}
} catch {}
}
get govConnected(): boolean {
return this.govWs?.readyState === WebSocket.OPEN;
}
get brConnected(): boolean {
return this.brWs?.readyState === WebSocket.OPEN;
}
}