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)
|