async def _send_to_users(self, qs_users: QuerySet, message_obj: ChannelMessage): """ Send the message to the users returned by the specified Django query set. This is an async method made private for calling it from the sync public method. :param qs_users: Django query set returning User models. Pk field will be requested via values_list(..). :param message_obj: Message to send. :return: """ connected_user_ids = self.get_connected_users() if not connected_user_ids: return # A workaround for "connection already closed" problem. # Looks like this code is being executed in a way that # the "connection" object it accesses is re-used for a long time and appears broken after some long delay. connection.close() layer = get_channel_layer() # type: RedisChannelLayer msg = {'type': 'send_to_client', 'message': message_obj.to_dict()} coros = list() for user_id in qs_users.filter(pk__in=connected_user_ids).values_list( 'pk', flat=True): send_to_user_coro = layer.group_send( self.user_id_to_group_name(user_id), msg) coros.append(send_to_user_coro) await asyncio.gather(*coros)
def send_to_all_users(self, message_obj: ChannelMessage): """ Send the message to all connected users. Each authenticated user is added to a special ALL group and this method sends the message into this group. :param message_obj: :return: """ layer = get_channel_layer() # type: RedisChannelLayer async_to_sync(layer.group_send)(ALL, {'type': 'send_to_client', 'message': message_obj.to_dict()})
def send_to_user(self, user_id, message_obj: ChannelMessage): """ Send the message to the specified user. :param user_id: ID of the user. :param message_obj: Message to send. :return: """ layer = get_channel_layer() # type: RedisChannelLayer async_to_sync(layer.group_send)(self.user_id_to_group_name(user_id), {'type': 'send_to_client', 'message': message_obj.to_dict()})
def send_to_users_by_ids(self, user_ids: List[int], message_obj: ChannelMessage): """ Send the message to the users returned by the specified Django query set. :param user_ids: user ids to send messages to :param message_obj: Message to send. :return: """ connected_user_ids = self.get_connected_users() if not connected_user_ids: return layer = get_channel_layer() # type: RedisChannelLayer async_to_sync(layer.group_send)(ALL, {'type': 'send_to_client', 'user_ids': user_ids, 'message': message_obj.to_dict()})
def send_to_users(self, qs_users: QuerySet, message_obj: ChannelMessage): """ Send the message to the users returned by the specified Django query set. :param qs_users: Django query set returning User models. Pk field will be requested via values_list(..). :param message_obj: Message to send. :return: """ connected_user_ids = self.get_connected_users() if not connected_user_ids: return user_ids: Set[int] = set(qs_users.filter(pk__in=connected_user_ids).values_list('pk', flat=True)) layer = get_channel_layer() # type: RedisChannelLayer async_to_sync(layer.group_send)(ALL, {'type': 'send_to_client', 'user_ids': list(user_ids), 'message': message_obj.to_dict()})
async def _send_to_users(self, qs_users: QuerySet, message_obj: ChannelMessage): """ Send the message to the users returned by the specified Django query set. This is an async method made private for calling it from the sync public method. :param qs_users: Django query set returning User models. Pk field will be requested via values_list(..). :param message_obj: Message to send. :return: """ connected_user_ids = self.get_connected_users() if not connected_user_ids: return layer = get_channel_layer() # type: RedisChannelLayer msg = {'type': 'send_to_client', 'message': message_obj.to_dict()} coros = list() for user_id in qs_users.filter(pk__in=connected_user_ids).values_list('pk', flat=True): send_to_user_coro = layer.group_send(self.user_id_to_group_name(user_id), msg) coros.append(send_to_user_coro) await asyncio.gather(*coros)