diff --git a/backend/src/socket/index.js b/backend/src/socket/index.js index 33f037f..d969956 100644 --- a/backend/src/socket/index.js +++ b/backend/src/socket/index.js @@ -21,6 +21,12 @@ function initializeSocket(httpServer) { origin: process.env.CORS_ORIGIN || 'http://localhost:8080', credentials: true, }, + // Ping/pong heartbeat configuration + pingInterval: 25000, // Send ping every 25 seconds + pingTimeout: 60000, // Wait 60 seconds for pong before considering disconnected + // Allow upgrade from polling to websocket + transports: ['polling', 'websocket'], + allowUpgrades: true, }); // Authentication middleware for Socket.IO diff --git a/frontend/src/hooks/useEventChat.js b/frontend/src/hooks/useEventChat.js index 3002ca7..9dbe13d 100644 --- a/frontend/src/hooks/useEventChat.js +++ b/frontend/src/hooks/useEventChat.js @@ -46,15 +46,37 @@ const useEventChat = (slug, userId, event, messagesContainerRef) => { return; } - // Socket event listeners - socket.on('connect', () => { + // Function to join room (used on connect and reconnect) + const joinRoom = () => { setIsConnected(true); - // Join event room socket.emit('join_event_room', { slug }); + }; + + // Check if already connected (socket instance may already be connected) + if (socket.connected) { + joinRoom(); + } + + // Socket event listeners + socket.on('connect', joinRoom); + + socket.on('disconnect', (reason) => { + setIsConnected(false); + console.log('🔌 Disconnected:', reason); }); - socket.on('disconnect', () => { - setIsConnected(false); + // Handle reconnection - rejoin room automatically + socket.on('reconnect', (attemptNumber) => { + console.log('🔄 Reconnected after', attemptNumber, 'attempts'); + // Room will be joined via 'connect' event + }); + + socket.on('reconnect_attempt', (attemptNumber) => { + console.log('🔄 Reconnection attempt', attemptNumber); + }); + + socket.on('reconnect_error', (error) => { + console.error('🔄 Reconnection error:', error); }); // Receive message history (initial 20 messages) @@ -92,8 +114,11 @@ const useEventChat = (slug, userId, event, messagesContainerRef) => { // Cleanup return () => { socket.emit('leave_event_room'); - socket.off('connect'); + socket.off('connect', joinRoom); socket.off('disconnect'); + socket.off('reconnect'); + socket.off('reconnect_attempt'); + socket.off('reconnect_error'); socket.off('message_history'); socket.off('event_message'); socket.off('active_users'); diff --git a/frontend/src/hooks/useMatchChat.js b/frontend/src/hooks/useMatchChat.js index f40567e..cc8d246 100644 --- a/frontend/src/hooks/useMatchChat.js +++ b/frontend/src/hooks/useMatchChat.js @@ -64,8 +64,18 @@ const useMatchChat = (match, userId, slug) => { // Socket event listeners socket.on('connect', joinMatchRoom); - socket.on('disconnect', () => { + socket.on('disconnect', (reason) => { setIsConnected(false); + console.log('🔌 Match chat disconnected:', reason); + }); + + // Handle reconnection + socket.on('reconnect', (attemptNumber) => { + console.log('🔄 Match chat reconnected after', attemptNumber, 'attempts'); + }); + + socket.on('reconnect_attempt', (attemptNumber) => { + console.log('🔄 Match chat reconnection attempt', attemptNumber); }); // Receive messages @@ -82,6 +92,8 @@ const useMatchChat = (match, userId, slug) => { return () => { socket.off('connect', joinMatchRoom); socket.off('disconnect'); + socket.off('reconnect'); + socket.off('reconnect_attempt'); socket.off('match_message'); }; }, [match, userId]); diff --git a/frontend/src/services/socket.js b/frontend/src/services/socket.js index 79fe2a6..2e6f931 100644 --- a/frontend/src/services/socket.js +++ b/frontend/src/services/socket.js @@ -26,9 +26,17 @@ export function connectSocket() { auth: { token, }, + // Reconnection settings reconnection: true, - reconnectionAttempts: 5, - reconnectionDelay: 1000, + reconnectionAttempts: Infinity, // Keep trying forever + reconnectionDelay: 1000, // Start with 1 second delay + reconnectionDelayMax: 5000, // Max 5 seconds between attempts + randomizationFactor: 0.5, // Add some randomness to prevent thundering herd + // Timeout settings + timeout: 20000, // 20 seconds connection timeout + // Transport settings - prefer websocket but start with polling for reliability + transports: ['polling', 'websocket'], + upgrade: true, }); socket.on('connect', () => {