base_agent/uas/event/event_handler.py

173 lines
6.5 KiB
Python
Raw Normal View History

2026-06-18 03:28:14 +00:00
# -*- 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)