How to get the log and result of websocket async_to_sync calling
I have websocket and simply send the mesasges to channel_layer
from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
'{}'.format(mychannelname),
{
"type": "chat_message",
"message": "send you"
}
)
It seems works well and messages goes to client browser, however I want to know if it works well or not from server.
Is it possible or can I get the number of clients connected to channel?
My consumers.py makes channels
import json
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
await self.send(text_data=json.dumps({
'channel_name': self.channel_name
}))
async def disconnect(self, close_code):
print("some disconnect")
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
print("receive data",text_data_json)
print("channel_name:",self.channel_name)
print("group_name:",self.room_group_name)
if text_data_json['type'] == "register":
self.user_id = text_data_json['message']
print("user_id is:",self.user_name)
#res = await self.save_message_to_db(message)
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': "nicelydone",
}
)
async def chat_message(self, event):
print("someone call chat_message")
message = event['message']
await self.send(text_data=json.dumps({
'message': message
}))
How to confirm if messages are reaching connected clients:
One way to check if each client is receiving the message is to implement an acknowledgment system. When a client receives a message in the chat_message
method, you can have the client send an acknowledgment message back to the server.
Here’s an example of how you can do it:
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log("Received message:", data.message);
// Send acknowledgment back to the server
socket.send(JSON.stringify({
'type': 'acknowledgment',
'message': 'Message received'
}));
};
Then, on the server, you can handle this acknowledgment in the receive
method to confirm delivery:
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message_type = text_data_json.get('type')
if message_type == "acknowledgment":
print(f"Acknowledgment received from {self.channel_name}")
# Continue with the rest of your logic here...
This way, each time the client receives a message, they send back an acknowledgment that you can log or track on the server.
How to get the number of connected clients in a channel group:
Django Channels doesn’t directly provide a built-in method to get the number of clients in a group. However, you can keep track of this manually by maintaining a count of active connections. For example:
- Increment a counter when
connect
is called. - Decrement the counter when
disconnect
is called.
You could use a cache like Redis to store and retrieve this count, which will persist across different worker processes.
Here’s how you might implement this:
from asgiref.sync import async_to_sync
from django.core.cache import cache
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]
# Increment connected client count
await self.update_client_count(1)
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
# Decrement connected client count
await self.update_client_count(-1)
await self.channel_layer.group_discard(self.room_group_name, self.channel_name)
@database_sync_to_async
def update_client_count(self, delta):
current_count = cache.get(self.room_group_name, 0)
new_count = current_count + delta
cache.set(self.room_group_name, new_count)
print(f"Current clients in {self.room_group_name}: {new_count}")
Here, cache can be set up to use Redis or Memcached, allowing you to store the room_group_name as the key and the count as the value.
This way, update_client_count will keep track of the current active connections in your channel group, and you can retrieve the number of connected clients by calling cache.get(room_group_name) wherever needed.