You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

74 lines
2.3 KiB

from __future__ import annotations
import asyncio
from collections import defaultdict, deque
from typing import TYPE_CHECKING, Any, DefaultDict, Deque, Dict, Optional, Tuple
from . import globals # pylint: disable=redefined-builtin
if TYPE_CHECKING:
from .element import Element
ClientId = str
ElementId = int
MessageType = str
Message = Tuple[ClientId, MessageType, Any]
update_queue: DefaultDict[ClientId, Dict[ElementId, Optional[Element]]] = defaultdict(dict)
message_queue: Deque[Message] = deque()
def enqueue_update(element: Element) -> None:
update_queue[element.client.id][element.id] = element
def enqueue_delete(element: Element) -> None:
update_queue[element.client.id][element.id] = None
def enqueue_message(message_type: MessageType, data: Any, target_id: ClientId) -> None:
message_queue.append((target_id, message_type, data))
async def _emit(message_type: MessageType, data: Any, target_id: ClientId) -> None:
await globals.sio.emit(message_type, data, room=target_id)
if is_target_on_air(target_id):
assert globals.air is not None
await globals.air.emit(message_type, data, room=target_id)
async def loop() -> None:
while True:
if not update_queue and not message_queue:
await asyncio.sleep(0.01)
continue
coros = []
try:
for client_id, elements in update_queue.items():
data = {
element_id: None if element is None else element._to_dict() # pylint: disable=protected-access
for element_id, element in elements.items()
}
coros.append(_emit('update', data, client_id))
update_queue.clear()
for target_id, message_type, data in message_queue:
coros.append(_emit(message_type, data, target_id))
message_queue.clear()
for coro in coros:
try:
await coro
except Exception as e:
globals.handle_exception(e)
except Exception as e:
globals.handle_exception(e)
await asyncio.sleep(0.1)
def is_target_on_air(target_id: str) -> bool:
if target_id in globals.clients:
return globals.clients[target_id].on_air
return target_id in globals.sio.manager.rooms