Creating a waiting queue in Django Channels?

Viewed 613

I am currently working on a "wait queue" application on my Django app using channels. I have a channel layer using Redis to handle the connections within a group. I am also using a model in my database to track the amount of users in the queue. My question is if there is an easier and more scalable way. Will there be any issues down the road with this?

class ChatConsumer(AsyncWebsocketConsumer):

    @database_sync_to_async
    def get_waiting_room(self):
        return WaitingRoom.objects.all().count()

    @database_sync_to_async
    def add_to_waiting_room(self, name):
        return WaitingRoom.objects.create(name=name)

    @database_sync_to_async
    def remove_from_waiting_room(self, name):
        return WaitingRoom.objects.filter(name=name).delete()

    async def connect(self):
        self.waiting_list = 'waiting_list'

        await self.channel_layer.group_add(
            self.waiting_list, self.channel_name)

        await self.accept()

    async def receive(self, text_data):
        self.text_data = json.loads(text_data)

        await self.add_to_waiting_room(self.text_data['user'])

        users = await self.get_waiting_room()

        await self.channel_layer.group_send(self.waiting_list, {
            'type': 'user_list',
            'users': str(users)
        })

    async def disconnect(self, close_code):

        await self.remove_from_waiting_room(name=self.text_data['user'])
        await self.channel_layer.group_discard(
            self.waiting_list,
            self.channel_name)

        users = await self.get_waiting_room()

        await self.channel_layer.group_send(self.waiting_list, {
            'type': 'user_list',
            'users': str(users)
        })

    async def user_list(self, event):
        users = event['users']

        await self.send(text_data=users)

When a user connects, they are added to a group in the channel_layer (Redis) and accepts the connection, when my user clicks a button, it sends a request to the channel and adds them to the waiting room (My Django model), on disconnect, it removes Model instance and sends a signal to the channel with an updated "User" count.

Is there a simpler way to do this? Will this method cause any roadblocks down the road?

Thanks in advance.

1 Answers

Browsers do not always close websocket connections cleanly, so I think there is a chance that disconnect() will never be fired. So you could get stale data in the database, or .connect() called twice in a row, leading to an integrity error.

Related