Django app websocket connected client getting empty set even after active connection in connection handler
I am build a django app, it has following architecure.
- apps.py
- handlers.py
- signals.py
- views.py
- urls.py
urls.py - It contains an endpoint there I have a view class from views.py. I capture POST request data there, this endpoint acts as a webhook.
views.py - A view class with post
method that handles incoming data to webhook endpoint. After getting data, I trigger a signal with data.
signals.py - It has a Signal object created for custom signal.
handlers.py - It has implementation of websockets
package, have connected clients in self.clients
property.
apps.py - Inside this in ready
method I am initializing WebSocketServer
class from handlers.py
, and on a given port in a separate thread.
Handler.py code
`import asyncio import websockets import json
from django.dispatch import receiver
from docapp.signals import gia_service_webhook_signal
class WebSocketServer: instance = None # Class variable to hold the singleton instance clients = set() # Set of connected clients
def __init__(self, host='localhost', port=8787):
self.host = host # Store the host
self.port = port # Store the port
WebSocketServer.instance = self # Set the singleton instance
# Connect the signal to the handler method
gia_service_webhook_signal.connect(self.handle_gia_service_webhook)
async def handle_connection(self, websocket, path):
print(f"New connection attempt on path: {path}") # Debugging
# Register a new client
self.clients.add(websocket)
print(f"Current clients after connection: {self.clients}") # Log current clients
try:
# self.clients.add(websocket)
if path == "/ws/gia_service_webhook":
# await websocket.send('ping123')
while True:
message = await websocket.recv()
print(f"Received message: {message}")
response = f"Received: {message}"
await websocket.send(response)
print(f"Sent response: {response}")
except websockets.exceptions.ConnectionClosed:
print("Connection closed")
finally:
self.clients.remove(websocket) # Unregister the client
print(f"Client disconnected. Current clients: {self.clients}") # Log current clients after disconnection
def get_clients(self):
return self.clients
def send_to_clients(self, message):
# Convert message to JSON before sending
json_message = json.dumps(message) # Convert the dictionary to a JSON string
asyncio.run(self._send_to_clients(json_message))
async def _send_to_clients(self, message):
print(f"Attempting to send message to clients: {message}") # Log the message to be sent
if self.clients: # Only send if there are connected clients
for client in self.clients:
try:
await client.send(message) # Send the message to the client
print(f"Message sent to client: {client}") # Log success
except Exception as e:
print(f"Error sending message to client {client}: {e}")
else:
print("No connected clients to send the message to. Current clients:", self.clients)
def handle_gia_service_webhook(self, sender, **kwargs):
# Extract relevant data from kwargs
action = kwargs.get('action') # Get the action parameter
user = kwargs.get('user') # Get the user parameter
# Create a dictionary to send as a message
data = {
'action': action,
'user': user,
}
# Handle the data as needed
print(f"Received signal with action in websocket class: {action}, user: {user}")
# Send to connected clients
self.send_to_clients(data)
def run(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
start_server = websockets.serve(self.handle_connection, self.host, self.port, reuse_address=True) # Use configurable host and port
loop.run_until_complete(start_server)
print(f"WebSocket server is running on ws://{self.host}:{self.port}/ws/gia_service_webhook")
loop.run_forever()
`
**Problem: **
I get empty set when access self.clients, when I am calling self.send_to_clients(data)
in signal handler. In method handle_connection
I get client connected and it's object. I need help to troubleshoot what's wrong here, It took my day to figure out still no luck.
I tried removing reuse_address=True
form websocket.serve
but that introduced another error of address already being used. put logs to find out why self.clients is empty but no luck.
I have django 5.0.8, python 3.11, websockets==13.1