fix(extension): Discord signal drop and UI freeze (async IO, regex filters, WS rate-limits) (v0.5.10)
This commit is contained in:
@@ -213,12 +213,21 @@ export class WSBridgeClient {
|
||||
this.logFn(`[WS] Connecting to ${this.hubUrl}...`);
|
||||
const ws = new WebSocket(this.hubUrl);
|
||||
|
||||
let connectTimeout: NodeJS.Timeout | null = null;
|
||||
const clearConnectTimeout = () => {
|
||||
if (connectTimeout) {
|
||||
clearTimeout(connectTimeout);
|
||||
connectTimeout = null;
|
||||
}
|
||||
};
|
||||
|
||||
// Detect API style: Node.js 'ws' module has .on(), browser WebSocket doesn't
|
||||
const isNodeWs = typeof ws.on === 'function';
|
||||
|
||||
if (isNodeWs) {
|
||||
// ─── Node.js ws module (EventEmitter API) ───
|
||||
ws.on('open', () => {
|
||||
clearConnectTimeout();
|
||||
this.logFn('[WS] Connection opened, authenticating...');
|
||||
this.ws = ws;
|
||||
this.connected = true;
|
||||
@@ -235,11 +244,18 @@ export class WSBridgeClient {
|
||||
});
|
||||
|
||||
ws.on('close', (code: number, reason: Buffer) => {
|
||||
clearConnectTimeout();
|
||||
const reasonStr = reason ? reason.toString('utf-8') : '';
|
||||
this.logFn(`[WS] Connection closed: code=${code} reason=${reasonStr}`);
|
||||
this._onDisconnect();
|
||||
});
|
||||
|
||||
ws.on('error', (err: any) => {
|
||||
clearConnectTimeout();
|
||||
this.logFn(`[WS] Connection error: ${err.message || err}`);
|
||||
this._onDisconnect();
|
||||
});
|
||||
|
||||
ws.on('pong', () => {
|
||||
// Server responded to our ping — connection is alive
|
||||
this.lastPongTime = Date.now();
|
||||
@@ -247,6 +263,7 @@ export class WSBridgeClient {
|
||||
} else {
|
||||
// ─── Browser-style WebSocket API (.onopen / .onmessage) ───
|
||||
ws.onopen = () => {
|
||||
clearConnectTimeout();
|
||||
this.logFn('[WS] Connection opened (browser API), authenticating...');
|
||||
this.ws = ws;
|
||||
this.connected = true;
|
||||
@@ -264,15 +281,29 @@ export class WSBridgeClient {
|
||||
};
|
||||
|
||||
ws.onclose = (event: any) => {
|
||||
clearConnectTimeout();
|
||||
this.logFn(`[WS] Connection closed: code=${event.code} reason=${event.reason || ''}`);
|
||||
this._onDisconnect();
|
||||
};
|
||||
|
||||
ws.onerror = (event: any) => {
|
||||
clearConnectTimeout();
|
||||
this.logFn(`[WS] Error: ${event.message || 'connection error'}`);
|
||||
this._onDisconnect();
|
||||
};
|
||||
}
|
||||
|
||||
// Connection timeout to prevent hanging if no close/error fires
|
||||
connectTimeout = setTimeout(() => {
|
||||
this.logFn('[WS] Connection timeout (15s) — forcing disconnect');
|
||||
if (this.ws) {
|
||||
try { this.ws.terminate(); } catch { try { this.ws.close(); } catch { } }
|
||||
} else if (ws) {
|
||||
try { ws.terminate(); } catch { try { ws.close(); } catch { } }
|
||||
}
|
||||
this._onDisconnect();
|
||||
}, 15000);
|
||||
|
||||
} catch (e: any) {
|
||||
this.logFn(`[WS] Connect failed: ${e.message}`);
|
||||
this._scheduleReconnect();
|
||||
@@ -448,13 +479,15 @@ export class WSBridgeClient {
|
||||
}
|
||||
}
|
||||
|
||||
private _flushQueue(): void {
|
||||
private async _flushQueue(): Promise<void> {
|
||||
if (this.messageQueue.length === 0) return;
|
||||
this.logFn(`[WS] Flushing ${this.messageQueue.length} queued messages`);
|
||||
this.logFn(`[WS] Flushing ${this.messageQueue.length} queued messages (paced)`);
|
||||
const queue = [...this.messageQueue];
|
||||
this.messageQueue = [];
|
||||
for (const msg of queue) {
|
||||
this._sendRaw(msg);
|
||||
// Pace the burst to avoid hitting the Hub's rate limit (60 msgs / 10s)
|
||||
await new Promise(r => setTimeout(r, 50));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user