173 lines
6.5 KiB
Python
173 lines
6.5 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
事件处理器基类与装饰器系统
|
||
─────────────────────────────────────────────────────────────────
|
||
提供两种注册处理器的方式:
|
||
1. 继承 BaseEventHandler 类(面向对象风格)
|
||
2. 使用 @on_event 装饰器(函数式风格)
|
||
─────────────────────────────────────────────────────────────────
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import functools
|
||
import inspect
|
||
import logging
|
||
from abc import ABC, abstractmethod
|
||
from typing import Callable, List, Optional, Union
|
||
|
||
from uas.event.event_model import Event
|
||
from uas.event.event_type import EventType
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
# ─────────────────────────────────────────────────────────────────
|
||
# 处理器描述符
|
||
# ─────────────────────────────────────────────────────────────────
|
||
|
||
class HandlerDescriptor:
|
||
"""
|
||
处理器注册描述符
|
||
记录处理器函数与其绑定的事件类型、优先级、过滤条件
|
||
"""
|
||
def __init__(
|
||
self,
|
||
fn: Callable,
|
||
event_types: List[Union[EventType, str]],
|
||
priority: int = 0, # 同类型处理器执行顺序(越小越先)
|
||
condition: Optional[Callable[[Event], bool]] = None,
|
||
once: bool = False, # 是否只执行一次
|
||
name: str = "",
|
||
):
|
||
self.fn = fn
|
||
self.event_types = [
|
||
t.value if isinstance(t, EventType) else t
|
||
for t in event_types
|
||
]
|
||
self.priority = priority
|
||
self.condition = condition
|
||
self.once = once
|
||
self.name = name or fn.__name__
|
||
self.call_count = 0
|
||
self.is_async = inspect.iscoroutinefunction(fn)
|
||
|
||
def matches(self, event: Event) -> bool:
|
||
"""检查事件是否匹配此处理器"""
|
||
type_match = (
|
||
event.type_key in self.event_types or
|
||
"*" in self.event_types # 通配符
|
||
)
|
||
if not type_match:
|
||
return False
|
||
if self.condition and not self.condition(event):
|
||
return False
|
||
return True
|
||
|
||
def __repr__(self):
|
||
return (f"Handler({self.name!r}, types={self.event_types}, "
|
||
f"priority={self.priority}, async={self.is_async})")
|
||
|
||
|
||
# ─────────────────────────────────────────────────────────────────
|
||
# 抽象基类(面向对象风格)
|
||
# ─────────────────────────────────────────────────────────────────
|
||
|
||
class BaseEventHandler(ABC):
|
||
"""
|
||
事件处理器抽象基类
|
||
子类实现 handle() 方法,并声明 event_types 属性
|
||
|
||
示例:
|
||
class DeviceErrorHandler(BaseEventHandler):
|
||
event_types = [EventType.DEVICE_ERROR]
|
||
priority = 10
|
||
|
||
def handle(self, event: Event) -> Optional[dict]:
|
||
print(f"处理设备错误: {event.params}")
|
||
return {"action": "restart"}
|
||
"""
|
||
|
||
event_types: List[Union[EventType, str]] = []
|
||
priority: int = 0
|
||
condition: Optional[Callable] = None
|
||
|
||
def __init__(self):
|
||
self.logger = logging.getLogger(self.__class__.__name__)
|
||
self._descriptor = HandlerDescriptor(
|
||
fn = self.handle,
|
||
event_types = self.event_types,
|
||
priority = self.priority,
|
||
condition = self.condition,
|
||
name = self.__class__.__name__,
|
||
)
|
||
|
||
@abstractmethod
|
||
def handle(self, event: Event):
|
||
"""
|
||
处理事件
|
||
:return: 可选的处理结果数据(写入 EventResult.data)
|
||
"""
|
||
...
|
||
|
||
@property
|
||
def descriptor(self) -> HandlerDescriptor:
|
||
return self._descriptor
|
||
|
||
|
||
# ─────────────────────────────────────────────────────────────────
|
||
# 装饰器(函数式风格)
|
||
# ─────────────────────────────────────────────────────────────────
|
||
|
||
# 全局装饰器注册表(供 EventBus 扫描)
|
||
_decorator_handlers: List[HandlerDescriptor] = []
|
||
|
||
|
||
def on_event(
|
||
*event_types: Union[EventType, str],
|
||
priority: int = 0,
|
||
condition: Optional[Callable[[Event], bool]] = None,
|
||
once: bool = False,
|
||
):
|
||
"""
|
||
事件处理器装饰器(函数式风格)
|
||
|
||
示例:
|
||
@on_event(EventType.DEVICE_ERROR, EventType.DEVICE_WARNING)
|
||
def handle_device_issue(event: Event):
|
||
print(f"设备问题: {event.message}")
|
||
|
||
@on_event(EventType.SYSTEM_HEARTBEAT, priority=-10)
|
||
async def async_heartbeat(event: Event):
|
||
await asyncio.sleep(0)
|
||
print("心跳处理(异步)")
|
||
|
||
# 带条件过滤
|
||
@on_event(EventType.DEVICE_ERROR,
|
||
condition=lambda e: e.params.get("code") == "E001")
|
||
def handle_e001(event: Event):
|
||
print("仅处理 E001 错误")
|
||
"""
|
||
def decorator(fn: Callable) -> Callable:
|
||
desc = HandlerDescriptor(
|
||
fn = fn,
|
||
event_types = list(event_types),
|
||
priority = priority,
|
||
condition = condition,
|
||
once = once,
|
||
name = fn.__name__,
|
||
)
|
||
_decorator_handlers.append(desc)
|
||
logger.debug(f"@on_event 注册: {desc}")
|
||
|
||
@functools.wraps(fn)
|
||
def wrapper(*args, **kwargs):
|
||
return fn(*args, **kwargs)
|
||
wrapper._handler_descriptor = desc
|
||
return wrapper
|
||
return decorator
|
||
|
||
|
||
def get_decorator_handlers() -> List[HandlerDescriptor]:
|
||
"""获取所有通过 @on_event 注册的处理器描述符"""
|
||
return list(_decorator_handlers) |