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

Back to Top