from channels.layers import get_channel_layer from asgiref.sync import async_to_sync from threading import Timer class WebSocketSender: """ Manages WebSocket notifications for users with individual buffering timers. """ def __init__(self): self._user_timers = {} # Dictionary to store user-specific timers self._buffer_timeout = 0.1 # Debounce timeout in seconds def send_user_message(self, user_id, device_id): """ Schedules a notification for a specific user with debouncing. """ print(f'>>> send message: {device_id}') # Cancel existing timer for this user if any if user_id in self._user_timers and self._user_timers[user_id]: self._user_timers[user_id].cancel() # Create new timer for this user self._user_timers[user_id] = Timer( self._buffer_timeout, self._send_message, args=[user_id, device_id] ) self._user_timers[user_id].start() def _send_message(self, user_id, device_id): """ Sends the WebSocket message for a specific user. """ channel_layer = get_channel_layer() group_name = f"sync_{user_id}" print(f">>> send to group {group_name}, device_id={device_id}") # print(f'channel_layer = {channel_layer}') device_id = device_id if device_id else "std_msg_lol" # a not empty message is required! async_to_sync(channel_layer.group_send)( group_name, {"type": "sync.update", "message": device_id} ) # Cleanup timer reference self._user_timers[user_id] = None # Create a singleton instance websocket_sender = WebSocketSender()