Sending messages to all user's devices with django channels

I have been developing project. It uses django channels for websockets. And I meet a problem with sending ws messages to all device of the same account that is logged in. It is not a rare situation when many users use same accounts while project is under developing. So when one user is logged in and the other user is logged in and then he is logged out the first user does not receive messages.

I tried to count devices but that method changes nothing.

My consumer is:

class NotificationConsumer(AsyncWebsocketConsumer):
    def __init__(self, *args, **kwargs):
        super().__init__(args, kwargs)
        self.user = None
        self.pool_name = None

    async def connect(self):
        self.user = self.scope["user"]
        self.pool_name = f"user_id_{self.scope['url_route']['kwargs']['user_id']}"
        await self.accept()

        # Join pool
        created = await self.add_online_user()
        if created:
            await self.channel_layer.group_add(
                self.pool_name,
                self.channel_name,
            )

    async def disconnect(self, close_code):
        # Leave room group
        removed = await self.remove_online_user()
        if removed:
            await self.channel_layer.group_discard(self.pool_name, self.channel_name)

    # Receive message from WebSocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]
        # Send message to room group
        await self.channel_layer.group_send(self.pool_name, {"type": "read_message", "message": message})

    # Receive message from room group
    async def notification_message(self, event):
        message = event["message"]
        await self.send(text_data=json.dumps({"message": [message]}, ensure_ascii=False))

    @database_sync_to_async
    def add_online_user(self):
        online_user = OnlineUser.objects.filter(user=self.user).first()
        if not online_user:
            OnlineUser.objects.create(user=self.user, counter=1)
            return True
        else:
            if online_user.counter:
                online_user.counter += 1
            else:
                online_user.counter = 2
            online_user.save()
            return False

    @database_sync_to_async
    def remove_online_user(self):
        online_user = OnlineUser.objects.filter(user=self.user).first()
        if online_user:
            if online_user.counter:
                if online_user.counter == 1 or online_user.counter is None:
                    online_user.delete()
                    return True
                else:
                    online_user.counter -= 1
                    online_user.save()
                    return False
            else:
                online_user.delete()
                return True

OnlineUser model:

class OnlineUser(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="online_user")
    counter = models.IntegerField(null=True, blank=True)

And send message method

def send_messages(notifications):
    channel_layer = get_channel_layer()
    mark_as_send = []
    for notification in notifications:
        online_user = User.objects.filter(online_user__user=notification.to_user)
        if online_user.exists():
            message = NotificationSerializer(notification).data
            data = {"type": "notification_message", "message": message}
            async_to_sync(channel_layer.group_send)(f"user_id_{notification.to_user.id}", data)
            mark_as_send.append(notification.id)

Finally I got that message is marked as send but it is not received. And it is not a problem with frontend because i do not receive message in Postman too.

only a single reader should get each written message. -- in docs So it is not supported by django channels. Am I right?

Вернуться на верх