I'm using django channels to handle websocket connections. If two clients send two messages at the same time I get a race condition using channel's WebsocketConsumer
. I'm assuming this happens because every connection to this consumer starts its own thread which is then handled in parallel with the other ones. So I thought I'd switch to AsyncWebsocketConsumer
. I put async
, await
, database_sync_to_async
and so on where necessary and everything works, but the race condition issue persists. I thought by using AsyncWebsocketConsumer
, every connection would be handled in the same thread and calling async def receive(...)
would block the thread so that every received message gets handled in sequence. What am I doing wrong?
I am now using a pg advisory lock, see https://github.com/Xof/django-pglocks.
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from django_pglocks import advisory_lock
class Consumer(AsyncWebsocketConsumer):
async def receive(self, text_data=None, bytes_data=None):
text_data = json.loads(text_data)
await database_sync_to_async(self.do_stuff)(text_data)
def do_stuff(self, text_data):
with advisory_lock("a lock"):
stuff = Stuff.objects.get(pk=text_data["stuff_id"])
# do things
stuff.save()
Edit: Because I need a lot of locks and postgresql allows only about a hundred connections I switched to python-redis-lock. The maximum number of connections is now only limited by the availability of file descriptors which can be set using ulimit.