diff --git a/__pycache__/extensions.cpython-313.pyc b/__pycache__/extensions.cpython-313.pyc index ac913cc..05104fc 100644 Binary files a/__pycache__/extensions.cpython-313.pyc and b/__pycache__/extensions.cpython-313.pyc differ diff --git a/entrypoint.sh b/entrypoint.sh index 38fb14e..1051690 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -52,4 +52,4 @@ init_admin() # Start the application echo "Starting application..." -exec gunicorn --bind 0.0.0.0:5000 app:app \ No newline at end of file +exec gunicorn --worker-class eventlet -w 1 --bind 0.0.0.0:5000 app:app \ No newline at end of file diff --git a/extensions.py b/extensions.py index 6396315..a965a67 100644 --- a/extensions.py +++ b/extensions.py @@ -7,4 +7,11 @@ from flask_wtf.csrf import CSRFProtect db = SQLAlchemy() login_manager = LoginManager() csrf = CSRFProtect() -socketio = SocketIO(cors_allowed_origins="*") \ No newline at end of file +socketio = SocketIO( + cors_allowed_origins="*", + async_mode='threading', + logger=True, + engineio_logger=True, + ping_timeout=60, + ping_interval=25 +) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 27949a6..9b2377a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,7 @@ python-dotenv==1.0.1 psycopg2-binary==2.9.9 gunicorn==21.2.0 Flask-SocketIO==5.3.6 -email_validator==2.1.0.post1 \ No newline at end of file +python-socketio==5.10.0 +python-engineio==4.8.0 +email_validator==2.1.0.post1 +simple-websocket==1.0.0 \ No newline at end of file diff --git a/templates/conversations/conversation.html b/templates/conversations/conversation.html index ee77acd..e4c31d1 100644 --- a/templates/conversations/conversation.html +++ b/templates/conversations/conversation.html @@ -399,11 +399,14 @@ if (typeof window.ChatManager === 'undefined') { // Create socket instance socket = io({ - transports: ['websocket'], - upgrade: false, - reconnection: false, - debug: true, - forceNew: false, + transports: ['websocket', 'polling'], // Allow fallback to polling + upgrade: true, // Enable transport upgrade + reconnection: true, // Enable reconnection + reconnectionAttempts: 5, // Number of reconnection attempts + reconnectionDelay: 1000, // Delay between reconnection attempts + timeout: 20000, // Connection timeout + debug: false, // Disable debug in production + forceNew: true, // Force new connection multiplex: false }); @@ -419,20 +422,37 @@ if (typeof window.ChatManager === 'undefined') { }); }); - socket.on('disconnect', function(reason) { - console.log('Disconnected from conversation:', { - reason: reason, - socketId: socket.id, - connectionState: state.connectionState - }); + socket.on('connect_error', function(error) { + console.error('Socket connection error:', error); state.connectionState.isConnected = false; state.connectionState.hasJoined = false; - state.connectionState.socketId = null; }); - socket.on('error', function(error) { - console.error('Socket error:', error); - cleanup(); + socket.on('reconnect_attempt', function(attemptNumber) { + console.log('Attempting to reconnect:', attemptNumber); + }); + + socket.on('reconnect', function(attemptNumber) { + console.log('Reconnected after', attemptNumber, 'attempts'); + state.connectionState.isConnected = true; + // Rejoin the conversation room after reconnection + if (!state.connectionState.hasJoined) { + socket.emit('join_conversation', { + conversation_id: conversationId, + timestamp: new Date().toISOString(), + socketId: socket.id + }); + state.connectionState.hasJoined = true; + } + }); + + socket.on('reconnect_error', function(error) { + console.error('Reconnection error:', error); + }); + + socket.on('reconnect_failed', function() { + console.error('Failed to reconnect'); + alert('Connection lost. Please refresh the page.'); }); instance = {