WebSocket Service
Relevant source files
The following files were used as context for generating this wiki page:The WebSocket service provides real-time, bidirectional communication between the FastAPI backend and the Next.js frontend. Its primary purpose is to instantly push updates to all connected clients, ensuring the Q&A dashboard reflects new questions and status changes without requiring users to refresh the page. This creates a live, interactive experience for all users on the forum.
The service is built around a central connection manager on the backend and a React Context provider on the frontend, which together handle connection lifecycle, state management, and event broadcasting.
Architecture Overview
The WebSocket architecture consists of a server-side component that manages client connections and a client-side component that establishes and maintains the connection, listens for messages, and updates the UI accordingly.
The following diagram illustrates the basic sequence of a client connecting and receiving a real-time update.
This sequence diagram shows a client connecting, receiving the initial list of all questions, and subsequently receiving a live update when another user creates a new question.
Sources: backend/api/questions.py:28-70, web/src/context/WebSocketContext.js:15-46
Backend Implementation (FastAPI)
The backend is responsible for accepting WebSocket connections, managing a pool of active clients, and broadcasting messages when relevant events occur.
Sources: backend/api/questions.py, backend/utils/socket_manager.py
Connection Management
Connection management is handled by the ConnectionManager class. This singleton class maintains a list of active WebSocket connections.
This diagram shows the structure of the ConnectionManager class, which is responsible for tracking all active client connections.
Sources: backend/utils/socket_manager.py
connect(websocket: WebSocket): Adds a new client's WebSocket connection to theactive_connectionslist.disconnect(websocket: WebSocket): Removes a client's connection from the list.broadcast(message: dict): Iterates through all active connections and sends the JSON-encoded message to each client.
An instance of this manager is created in backend/api/questions.py to be used by the API endpoints.
Sources: backend/api/questions.py:29, backend/utils/socket_manager.py:5-18
WebSocket Endpoint: /questions/ws
The primary WebSocket endpoint is defined in the questions API router.
- Endpoint:
GET /questions/ws - Function:
websocket_endpoint(websocket: WebSocket)
When a client connects to this endpoint:
- The connection is accepted and registered with the
ConnectionManager. - The server immediately queries the database for all existing questions.
- The questions are sorted by status (
Escalated,Pending,Answered) and then by creation timestamp. - A message of type
questions_listcontaining the full, sorted list of questions is sent to the newly connected client. - The server then enters a loop, holding the connection open to allow for future broadcasts. It does not process incoming messages from the client in this loop (
await websocket.receive_text()). - If the client disconnects or an error occurs, the connection is removed from the manager.
Sources: backend/api/questions.py:73-95
Broadcasting Events
The system broadcasts messages to all connected clients when specific events happen. This is achieved by calling the manager.broadcast() method from standard HTTP endpoints.
The following diagram shows the flow when a new question is created.
This flowchart illustrates how a standard HTTP POST request triggers a WebSocket broadcast to all clients.
Sources: backend/api/questions.py:31-70
Key broadcast events include:
question_created: Triggered in thePOST /questionsendpoint after a new question is successfully saved to the database. The payload contains the new question object.question_updated: Triggered in thePATCH /questions/{question_id}endpoint when an admin changes a question's status. The payload contains the updated question object.
Sources: backend/api/questions.py:63-68, backend/api/questions.py:180-185
Frontend Implementation (Next.js)
The frontend uses React's Context API to manage the WebSocket connection and share its state across the application.
Sources: web/src/context/WebSocketContext.js, web/src/app/forum/page.js
Configuration
The WebSocket URL is configured via an environment variable.
| Variable | Description | Default Value | File |
|---|---|---|---|
NEXT_PUBLIC_WS_BASE_URL | The base URL for the WebSocket server. | ws://localhost:8000 | web/src/config/api.js |
Sources: web/src/config/api.js:2
WebSocketProvider and useWebSocket Hook
The WebSocketProvider component wraps the application and manages the WebSocket lifecycle.
- State:
isConnected: A boolean flag indicating the connection status.questions: An array holding the list of questions, updated in real-time.
- Functions:
connect(): Establishes a connection to${WS_BASE_URL}/questions/ws. It sets uponopen,onmessage,onerror, andonclosehandlers. It also includes a reconnection mechanism that attempts to reconnect 3 seconds after a connection is closed.disconnect(): Closes the WebSocket connection.send(message): Sends a JSON-stringified message to the server (currently not used for client-to-server data flow in the forum).
The useWebSocket hook provides components with access to this context.
Sources: web/src/context/WebSocketContext.js, web/src/app/layout.js:20-22
Message Handling
The onmessage handler within WebSocketContext.js is responsible for processing incoming messages from the server and updating the application's state.
| Message Type | Payload | Action |
|---|---|---|
questions_list | { "type": "questions_list", "data": [...] } | Replaces the entire questions state with the data array. This is used for the initial data load. |
question_created | { "type": "question_created", "data": {...} } | Prepends the new question from data to the beginning of the questions state array, if it doesn't already exist. |
question_updated | { "type": "question_updated", "data": {...} } | Finds the corresponding question in the questions state by id and updates it with the new data. |
Sources: web/src/context/WebSocketContext.js:28-44
Component Integration
The ForumPage component uses the useWebSocket hook to get the connection status and the live list of questions.
// web/src/app/forum/page.js
export default function ForumPage() {
const { user, token } = useAuth();
const { isConnected, connect, questions } = useWebSocket();
useEffect(() => {
if (isConnected === false) {
connect();
}
}, [isConnected, connect]);
// ... render UI
}
The component displays a connection status indicator and renders the QuestionList component, passing the questions state to it. When the WebSocket context updates the questions state, the UI re-renders automatically to show the changes.
Sources: web/src/app/forum/page.js:10-24, web/src/app/forum/page.js:40-45