Ä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:
Torsten Schulz (local)
2025-09-15 08:45:11 +02:00
parent 8f4327efb5
commit d475e8b2f7
3 changed files with 188 additions and 7 deletions

View File

@@ -8,6 +8,7 @@ import { io } from 'socket.io-client';
const store = createStore({
state: {
isLoggedIn: localStorage.getItem('isLoggedIn') === 'true',
connectionStatus: 'disconnected', // 'connected', 'connecting', 'disconnected', 'error'
user: JSON.parse(localStorage.getItem('user')) || null,
language: navigator.language.startsWith('de') ? 'de' : 'en',
menu: JSON.parse(localStorage.getItem('menu')) || [],
@@ -45,6 +46,9 @@ const store = createStore({
setSocket(state, socket) {
state.socket = socket;
},
setConnectionStatus(state, status) {
state.connectionStatus = status;
},
clearSocket(state) {
if (state.socket) {
state.socket.disconnect();
@@ -86,6 +90,7 @@ const store = createStore({
if (currentSocket) {
currentSocket.disconnect();
}
commit('setConnectionStatus', 'connecting');
const socketIoUrl = import.meta.env.VITE_SOCKET_IO_URL || import.meta.env.VITE_API_BASE_URL;
console.log('🔌 Initializing Socket.io connection to:', socketIoUrl);
const socket = io(socketIoUrl, {
@@ -95,28 +100,40 @@ const store = createStore({
socket.on('connect', () => {
console.log('✅ Socket.io connected successfully');
retryCount = 0; // Reset retry counter on successful connection
commit('setConnectionStatus', 'connected');
const idForSocket = state.user?.hashedId || state.user?.id;
if (idForSocket) socket.emit('setUserId', idForSocket);
});
socket.on('disconnect', (reason) => {
console.warn('❌ Socket.io disconnected:', reason);
commit('setConnectionStatus', 'disconnected');
retryConnection(connectSocket);
});
socket.on('connect_error', (error) => {
console.error('❌ Socket.io connection error:', error);
console.error('❌ URL attempted:', import.meta.env.VITE_API_BASE_URL);
commit('setConnectionStatus', 'error');
});
commit('setSocket', socket);
};
let retryCount = 0;
const maxRetries = 10;
const retryConnection = (reconnectFn) => {
if (retryCount >= maxRetries) {
console.error('❌ Max retry attempts reached for Socket.io');
return;
}
retryCount++;
const delay = Math.min(1000 * Math.pow(1.5, retryCount - 1), 30000); // Exponential backoff, max 30s
console.log(`🔄 Retrying Socket.io connection in ${delay}ms (attempt ${retryCount}/${maxRetries})`);
setTimeout(() => {
console.log('Retrying Socket.io connection...');
reconnectFn();
}, 1000); // Retry every second
}, delay);
};
connectSocket();
@@ -236,14 +253,20 @@ const store = createStore({
};
let retryCount = 0;
const maxRetries = 5;
const maxRetries = 15; // Increased max retries
const retryConnection = (reconnectFn) => {
if (retryCount >= maxRetries) {
console.error('❌ Max retry attempts reached for Daemon WebSocket');
// Reset counter after a longer delay to allow for network recovery
setTimeout(() => {
retryCount = 0;
console.log('🔄 Resetting Daemon WebSocket retry counter - attempting reconnection');
reconnectFn();
}, 60000); // Wait 1 minute before resetting
return;
}
retryCount++;
const delay = Math.min(1000 * Math.pow(2, retryCount - 1), 10000); // Exponential backoff, max 10s
const delay = Math.min(1000 * Math.pow(1.5, retryCount - 1), 30000); // Exponential backoff, max 30s
console.log(`🔄 Retrying Daemon WebSocket connection in ${delay}ms (attempt ${retryCount}/${maxRetries})`);
setTimeout(() => {
reconnectFn();
@@ -272,6 +295,7 @@ const store = createStore({
socket: state => state.socket,
daemonSocket: state => state.daemonSocket,
menuNeedsUpdate: state => state.menuNeedsUpdate,
connectionStatus: state => state.connectionStatus,
},
modules: {
dialogs,