feat(websocket): Resolve ticket WebSocket disconnection/reconnection issue

This commit addresses the persistent WebSocket disconnection and reconnection
problem experienced with ticket updates. The root cause was identified as the
Django backend not running as an ASGI server, which is essential for WebSocket
functionality, and incorrect WebSocket routing.

The following changes were made:

- **Frontend ():**
  - Updated to append the  from cookies to the WebSocket URL's
    query parameter for authentication, ensuring the token is sent with the
    WebSocket connection request.

- **Backend Configuration:**
  - **:** Modified to explicitly
    start the Daphne ASGI server using  instead
    of . This ensures the backend runs in ASGI
    mode, capable of handling WebSocket connections.
  - **:** Removed 'daphne' from
    . Daphne is an ASGI server, not a traditional Django
    application, and its presence in  was causing application
    startup failures.
  - **:**
    - Removed  from  as it
      conflicts with Channels' ASGI server takeover.
    - Explicitly set  to ensure
      the ASGI entry point is correctly referenced.
  - **:** Added 'channels'
    to , ensuring the Channels application is correctly loaded
    within the multi-tenant setup, enabling ASGI functionality.

- **Backend Middleware & Routing:**
  - **:** Implemented a custom
     to authenticate WebSocket connections using an
     from either a query parameter or cookies. This middleware
    ensures proper user authentication for WebSocket sessions. Debugging
    prints with  were added for better visibility.
  - **:** Adjusted WebSocket URL regexes
    to  for robustness, ensuring correct matching
    regardless of leading/trailing slashes in the path.

These changes collectively ensure that WebSocket connections are properly
initiated by the frontend, authenticated by the backend, and served by
an ASGI-compliant server, resolving the frequent disconnection/reconnection
issue.
This commit is contained in:
poduck
2025-12-01 01:40:45 -05:00
parent be3b5b2d08
commit a274d70cec
7 changed files with 103 additions and 9 deletions

View File

@@ -2,6 +2,8 @@ import { useEffect, useRef, useCallback } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { toast } from 'react-hot-toast';
import { useCurrentUser } from './useAuth';
import { getBaseDomain } from '../utils/domain';
import { getCookie } from '../utils/cookies';
interface TicketWebSocketMessage {
type: 'new_ticket' | 'ticket_update' | 'ticket_deleted' | 'new_comment' | 'ticket_assigned' | 'ticket_status_changed';
@@ -111,10 +113,16 @@ export const useTicketWebSocket = (options: UseTicketWebSocketOptions = {}) => {
return;
}
// Determine WebSocket URL - connect to backend on port 8000
// Determine WebSocket URL using same logic as API config
const baseDomain = getBaseDomain();
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsHost = window.location.hostname + ':8000';
const wsUrl = `${protocol}//${wsHost}/ws/tickets/`;
// For localhost or lvh.me, use port 8000. In production, no port (Traefik handles it)
const isDev = baseDomain === 'localhost' || baseDomain === 'lvh.me';
const port = isDev ? ':8000' : '';
const token = getCookie('access_token');
const wsUrl = `${protocol}//api.${baseDomain}${port}/ws/tickets/?token=${token}`;
console.log('Connecting to ticket WebSocket:', wsUrl);