base_agent/uas/event/event_handler.py

173 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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