karl/app/events/__init__.py
2025-10-31 00:01:45 +01:00

41 lines
1 KiB
Python

from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass
from functools import wraps
from typing import Dict, List, Callable
from injectable import injectable, inject
@dataclass
class Event:
pass
@injectable(singleton=True)
class SimpleEventBus:
def __init__(self):
self._handlers: Dict[type, List[Callable]] = {}
self._executor = ThreadPoolExecutor()
def publish(self, event: Event) -> None:
for handler in self._handlers.get(type(event), []):
# Fire-and-forget execution
self._executor.submit(handler, event)
def subscribe(self, event_type: type, handler: Callable) -> None:
if event_type not in self._handlers:
self._handlers[event_type] = []
self._handlers[event_type].append(handler)
@staticmethod
def on(event: type) -> Callable:
def outer(func):
inject(SimpleEventBus).subscribe(event, func)
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
return outer