You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from collections import defaultdict
|
|
from collections.abc import Callable
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
logger = logging.getLogger("iti.events")
|
|
|
|
|
|
class EventBus:
|
|
def __init__(self, *, max_workers: int = 10) -> None:
|
|
self._handlers: dict[str, list[Callable]] = defaultdict(list)
|
|
self._executor = ThreadPoolExecutor(max_workers=max_workers)
|
|
|
|
def on(self, event_name: str):
|
|
def decorator(func: Callable) -> Callable:
|
|
self.register_handler(event_name, func)
|
|
return func
|
|
|
|
return decorator
|
|
|
|
def register_handler(self, event_name: str, handler: Callable) -> None:
|
|
self._handlers[event_name].append(handler)
|
|
|
|
def emit(self, event_name: str, *args, async_mode: bool = False, **kwargs) -> None:
|
|
for handler in list(self._handlers.get(event_name, [])):
|
|
if async_mode:
|
|
self._executor.submit(self._run_handler, handler, *args, **kwargs)
|
|
else:
|
|
self._run_handler(handler, *args, **kwargs)
|
|
|
|
def _run_handler(self, handler: Callable, *args, **kwargs) -> None:
|
|
try:
|
|
handler(*args, **kwargs)
|
|
except Exception:
|
|
logger.exception("event handler failed: %s", handler)
|
|
|
|
|
|
eventbus = EventBus()
|