Änderung: Verbesserung der Verbindungsverwaltung und Benutzeroberfläche in mehreren Komponenten
Änderungen: - Hinzufügung eines Verbindungsstatus-Indicators in der AppHeader.vue, der den aktuellen Verbindungsstatus anzeigt. - Erweiterung der MultiChatDialog.vue um verbesserte Netzwerkereignisbehandlungen und eine Herzschlag-Logik zur Aufrechterhaltung der WebSocket-Verbindung. - Anpassungen im Store zur Verwaltung des Verbindungsstatus und zur Implementierung von Wiederverbindungslogik mit exponentiellem Backoff. - Diese Anpassungen verbessern die Benutzererfahrung durch klare Statusanzeigen und erhöhen die Stabilität der WebSocket-Verbindungen.
This commit is contained in:
@@ -180,7 +180,11 @@ export default {
|
||||
isPicking: false,
|
||||
maxLightness: 92, // exclude extremely light colors (>% L)
|
||||
// Reconnect control
|
||||
reconnectIntervalMs: 5000,
|
||||
reconnectIntervalMs: 3000,
|
||||
reconnectAttempts: 0,
|
||||
maxReconnectAttempts: 20,
|
||||
heartbeatInterval: null,
|
||||
heartbeatIntervalMs: 30000, // 30 seconds
|
||||
connectAttemptTimeout: null,
|
||||
joinFallbackTimer: null,
|
||||
// Faster handshake watchdog separate from reconnect interval
|
||||
@@ -258,6 +262,9 @@ export default {
|
||||
this.opened = false;
|
||||
console.log('[Chat WS] dialog close — closing websocket');
|
||||
this.disconnectChatSocket();
|
||||
// Remove network event listeners
|
||||
window.removeEventListener('online', this.onOnline);
|
||||
window.removeEventListener('offline', this.onOffline);
|
||||
},
|
||||
onOptionsToggle(e) {
|
||||
e?.stopPropagation?.();
|
||||
@@ -270,11 +277,18 @@ export default {
|
||||
this.showOptions = false;
|
||||
},
|
||||
onOnline() {
|
||||
console.log('[Chat WS] Network online detected');
|
||||
if (this.opened && !this.chatConnected && !this.connectRacing && (!this.chatWs || this.chatWs.readyState !== WebSocket.OPEN)) {
|
||||
console.log('[Chat WS] online — attempting reconnect');
|
||||
this.reconnectAttempts = 0; // Reset attempts on network recovery
|
||||
this.reconnectIntervalMs = 3000; // Reset to base interval
|
||||
this.connectChatSocket();
|
||||
}
|
||||
},
|
||||
onOffline() {
|
||||
console.log('[Chat WS] Network offline detected');
|
||||
this.setStatus('disconnected');
|
||||
},
|
||||
async loadRooms() {
|
||||
try {
|
||||
const data = await fetchPublicRooms();
|
||||
@@ -315,6 +329,9 @@ export default {
|
||||
// Stelle die WS-Verbindung her, wenn der Dialog geöffnet wird
|
||||
this.opened = true;
|
||||
this.connectChatSocket();
|
||||
// Add network event listeners
|
||||
window.addEventListener('online', this.onOnline);
|
||||
window.addEventListener('offline', this.onOffline);
|
||||
},
|
||||
connectChatSocket() {
|
||||
if (this.connectRacing) return; // avoid overlapping races
|
||||
@@ -413,6 +430,9 @@ export default {
|
||||
this.wsUrl = url;
|
||||
this.chatWs = ws;
|
||||
this.transportConnected = true;
|
||||
this.reconnectAttempts = 0; // Reset reconnect counter on successful connection
|
||||
this.reconnectIntervalMs = 3000; // Reset to base interval
|
||||
this.startHeartbeat(); // Start heartbeat to keep connection alive
|
||||
console.log('[Chat WS] open in', dt, 'ms', '| protocol:', ws.protocol || '(none)', '| url:', url);
|
||||
// Close all other candidates
|
||||
this.pendingWs.forEach(r => {
|
||||
@@ -569,7 +589,21 @@ export default {
|
||||
},
|
||||
scheduleReconnect() {
|
||||
if (this.reconnectTimer) return;
|
||||
console.log('[Chat WS] scheduleReconnect in', this.reconnectIntervalMs, 'ms', '| opened:', this.opened);
|
||||
|
||||
// Check if we've exceeded max attempts
|
||||
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
||||
console.error('[Chat WS] Max reconnect attempts reached, waiting longer before retry');
|
||||
this.reconnectAttempts = 0; // Reset counter
|
||||
this.reconnectIntervalMs = 30000; // Wait 30 seconds
|
||||
} else {
|
||||
this.reconnectAttempts++;
|
||||
// Use exponential backoff with jitter
|
||||
const baseDelay = Math.min(3000 * Math.pow(1.5, this.reconnectAttempts - 1), 15000);
|
||||
const jitter = Math.random() * 1000; // Add up to 1 second jitter
|
||||
this.reconnectIntervalMs = baseDelay + jitter;
|
||||
}
|
||||
|
||||
console.log('[Chat WS] scheduleReconnect in', Math.round(this.reconnectIntervalMs), 'ms', '| opened:', this.opened, '| attempt:', this.reconnectAttempts);
|
||||
this.reconnectTimer = setTimeout(() => {
|
||||
this.reconnectTimer = null;
|
||||
if (this.opened && !this.chatConnected) {
|
||||
@@ -594,6 +628,7 @@ export default {
|
||||
clearTimeout(this.reconnectTimer);
|
||||
this.reconnectTimer = null;
|
||||
}
|
||||
this.stopHeartbeat(); // Stop heartbeat when disconnecting
|
||||
this.cleanupPendingSockets();
|
||||
if (this.connectOpenTimer) { clearTimeout(this.connectOpenTimer); this.connectOpenTimer = null; }
|
||||
if (this.connectAttemptTimeout) { clearTimeout(this.connectAttemptTimeout); this.connectAttemptTimeout = null; }
|
||||
@@ -613,6 +648,35 @@ export default {
|
||||
this.usersInRoom = [];
|
||||
this.selectedTargetUser = null;
|
||||
},
|
||||
startHeartbeat() {
|
||||
this.stopHeartbeat(); // Clear any existing heartbeat
|
||||
if (!this.opened || !this.chatConnected) return;
|
||||
|
||||
this.heartbeatInterval = setInterval(() => {
|
||||
if (!this.chatWs || this.chatWs.readyState !== WebSocket.OPEN) {
|
||||
console.warn('[Chat WS] Heartbeat failed - connection not open, attempting reconnect');
|
||||
this.stopHeartbeat();
|
||||
this.scheduleReconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Send a ping message to keep connection alive
|
||||
this.wsSend({ type: 'ping' });
|
||||
console.log('[Chat WS] Heartbeat sent');
|
||||
} catch (error) {
|
||||
console.warn('[Chat WS] Heartbeat failed:', error);
|
||||
this.stopHeartbeat();
|
||||
this.scheduleReconnect();
|
||||
}
|
||||
}, this.heartbeatIntervalMs);
|
||||
},
|
||||
stopHeartbeat() {
|
||||
if (this.heartbeatInterval) {
|
||||
clearInterval(this.heartbeatInterval);
|
||||
this.heartbeatInterval = null;
|
||||
}
|
||||
},
|
||||
getSelectedRoomName() {
|
||||
const r = this.rooms.find(x => x.id === this.selectedRoom);
|
||||
return r?.title || r?.name || '';
|
||||
|
||||
Reference in New Issue
Block a user