ADR 0006: Event System Priorities and Batching¶
Status¶
Accepted (Implemented)
Context¶
The EventBus system handles all internal event communication. Two enhancements were proposed:
- Event Priorities: Allow handlers to specify execution order
- Event Batching: Optimize bulk event publishing (e.g., during device discovery)
Decision¶
Implement both features as backward-compatible additions to EventBus.
Event Priorities¶
Added EventPriority enum with four levels:
class EventPriority(IntEnum):
"""Priority levels for event handlers."""
LOW = 0 # Cleanup, notifications
NORMAL = 50 # Standard application logic (default)
HIGH = 100 # Critical state updates
CRITICAL = 200 # Logging/metrics, must run first
Usage:
bus.subscribe(
event_type=DataPointUpdatedEvent,
event_key=None,
handler=my_handler,
priority=EventPriority.HIGH, # Called before NORMAL handlers
)
Execution order:
- Higher priority handlers execute first (CRITICAL > HIGH > NORMAL > LOW)
- Within same priority, handlers execute in subscription order (FIFO)
- Default priority is NORMAL for backward compatibility
Event Batching¶
Added EventBatch class for efficient bulk publishing:
class EventBatch:
"""Collects events for batched publishing."""
def __init__(self, *, bus: EventBus) -> None:
self._bus = bus
self._events: list[Event] = []
def add(self, *, event: Event) -> None:
self._events.append(event)
async def flush(self) -> None:
# Group events by type for efficient handler lookup
await self._bus.publish_batch(events=self._events)
self._events.clear()
Usage:
# Context manager for automatic flush
async with EventBatch(bus=event_bus) as batch:
batch.add(event=DeviceStateChangedEvent(...))
batch.add(event=DeviceStateChangedEvent(...))
# Events published when context exits
# Or manual usage
batch = EventBatch(bus=event_bus)
batch.add(event=event1)
batch.add_all(events=[event2, event3])
await batch.flush()
Consequences¶
Advantages¶
- Backward compatible: Existing code works unchanged (default NORMAL priority)
- Flexible ordering: Critical handlers (logging, metrics) can run first
- Performance optimization: Batching reduces handler lookup overhead during bulk operations
- Clean API: Context manager pattern ensures events are always flushed
Disadvantages¶
- Slightly more complex EventBus: Priority sorting and batch handling add code
- Potential for misuse: Overuse of CRITICAL priority could cause unexpected behavior
Use Cases¶
Event Priorities:
- CRITICAL: Logging handlers that must capture all events
- HIGH: Security-related state updates
- NORMAL: Standard application logic
- LOW: Analytics, cleanup operations
Event Batching:
- Device discovery (many DeviceCreatedEvents)
- Bulk value updates
- System startup/shutdown sequences
Alternatives Considered¶
1. Middleware/Interceptor Pattern for Priorities¶
Rejected: More complex than simple priority ordering. Overkill for the use case.
2. Separate High-Priority Event Bus¶
Rejected: Would split event handling logic. Single bus with priorities is cleaner.
3. Async Queue with Worker Pool for Batching¶
Rejected: Adds complexity. Simple batch collection and flush is sufficient.
References¶
aiohomematic/central/events/bus.py- EventBus implementationdocs/architecture.md- "Event System Enhancements: Implemented" section
Created: 2025-12-10 Author: Architecture Review