Django Channels stops working with self.receive_lock.locked error

Viewed 585

I'm struggling with a problem using Django Channels to make a notification system. It works fine in local. In production (on Webfaction), it will work for fine for a few minutes, and then stop working with the following error message:

ERROR - server - Exception inside application: 
  File "/home/client/.virtualenvs/project/lib/python3.6/site-packages/channels/sessions.py", line 175, in __call__
    return await self.inner(receive, self.send)
  File "/home/client/.virtualenvs/project/lib/python3.6/site-packages/channels/middleware.py", line 41, in coroutine_call
await inner_instance(receive, send)
  File "/home/client/.virtualenvs/project/lib/python3.6/site-packages/channels/consumer.py", line 54, in __call__
await await_many_dispatch([receive, self.channel_receive], self.dispatch)
  File "/home/client/.virtualenvs/project/lib/python3.6/site-packages/channels/utils.py", line 57, in await_many_dispatch
await task
  File "/home/client/.virtualenvs/project/lib/python3.6/site-packages/channels_redis/core.py", line 400, in receive
assert not self.receive_lock.locked()

I'm using:

  • aioredis==1.1.0
  • asgiref=2.3.2
  • channels==2.1.3
  • channels-redis==2.3.0
  • django==2.1.2
  • Redis 4.0.11
  • Python 3.6.6

This is all using django's development server.

My consumer looks like this:

class NotificationConsumer (AsyncJsonWebsocketConsumer):
    slight_ordering = True

    async def connect (self):
        self.user = self.scope["user"]
        await self.accept()
        group_name = "notifications_{}".format(self.user.employee.pk)
        await self.channel_layer.group_add(group_name, self.channel_name)

    async def disconnect (self, code):
        self.user = self.scope["user"]
        group_name = "notifications_{}".format(self.user.employee.pk)
        await self.channel_layer.group_discard (group_name, self.channel_name)

    async def user_notification (self, event):
        await self.send_json(event)

The notification is sent when created, using a post_save signal:

@receiver(post_save, sender=Notification)
def new_notification (sender, instance, **kwargs):
    channel_layer = get_channel_layer()
    group_name = "notifications_{}".format(instance.employee.pk)
    async_to_sync(channel_layer.group_send)(
       group_name, {
           "type": "user.notification",
           "event": "New notification",
           "notification_pk": instance.pk,
       }
    )

My routing looks like this:

application = ProtocolTypeRouter({
    'websocket': AuthMiddlewareStack(
        URLRouter(
            [url(r'^notifications/$', NotificationConsumer),]
        )
    ),
})

And finally, I'm using WebSocketBridge on the frontend:

const webSocketBridge = new channels.WebSocketBridge();
webSocketBridge.connect('/notifications/');
webSocketBridge.listen(function(action, stream){
   //show the notification
});

If anyone has an idea of what could be happening and why I get this self.receive_lock.locked() error, I'd appreciate it a lot.

Thanks

1 Answers

This issue got fixed in channels-redis version 2.3.3 Update channels-redis to 2.3.3 In case this throws any further errors or doesn't support your installation then follow the link below to update your core.py file. Though editing the package is not recommended, this will fix the lock issue. Link

Related