# -*- coding: utf-8 -*- """ Action 执行上下文 ───────────────────────────────────────────────────────────────── ActionContext 在处理函数执行期间提供: - 共享数据存储(跨 Action 传递状态) - Event 收集器(处理函数产生的 Event 暂存于此) - 进度上报接口 - 取消/暂停检查接口 ───────────────────────────────────────────────────────────────── """ from __future__ import annotations import logging import threading from typing import Any, Callable, Dict, List, Optional logger = logging.getLogger(__name__) class ActionContext: """ Action 执行上下文(每次执行独立实例) 处理函数签名: def my_handler(action: Action, ctx: ActionContext) -> Any: # 产生事件 ctx.emit_event(make_event(EventType.DEVICE_DATA_RECEIVED, ...)) ctx.emit_event(make_event(EventType.DEVICE_STATUS_CHANGED, ...)) # 上报进度 ctx.report_progress(50, "处理中...") # 检查取消 if ctx.is_cancelled: return None return {"result": "ok"} """ def __init__( self, action, # Action 对象 shared_store: Optional[Dict] = None, # 全局共享数据 progress_cb: Optional[Callable] = None, ): self._action = action self._events: List[Any] = [] # 收集产生的 Event 对象 self._store: Dict[str, Any] = shared_store if shared_store is not None else {} self._lock = threading.Lock() self._progress_cb = progress_cb self._progress: int = 0 self._status_msg: str = "" self.logger = logging.getLogger( f"ActionContext[{action.type_key}:{action.action_id[:8]}]" ) # ── Event 收集 ──────────────────────────────────────────────── def emit_event(self, event: Any) -> None: """ 在处理函数中产生一个 Event 对象 Event 将被收集后统一由 ActionExecutor 提交到 EventBus """ with self._lock: self._events.append(event) self.logger.debug(f"产生事件: {event}") def emit_events(self, events: List[Any]) -> None: """批量产生多个 Event 对象""" for event in events: self.emit_event(event) @property def collected_events(self) -> List[Any]: """获取所有已收集的 Event 对象(只读副本)""" with self._lock: return list(self._events) # ── 进度上报 ────────────────────────────────────────────────── def report_progress(self, percent: int, message: str = "") -> None: """ 上报执行进度(0~100) :param percent: 进度百分比 :param message: 进度描述 """ self._progress = max(0, min(100, percent)) self._status_msg = message if self._progress_cb: self._progress_cb(self._action.action_id, self._progress, message) self.logger.debug(f"进度 {self._progress}% - {message}") @property def progress(self) -> int: return self._progress @property def status_message(self) -> str: return self._status_msg # ── 取消/暂停检查 ───────────────────────────────────────────── @property def is_cancelled(self) -> bool: """处理函数内部轮询此属性以响应取消请求""" return self._action.cancel_requested @property def is_paused(self) -> bool: return self._action.pause_requested def check_cancel(self) -> bool: """ 检查取消标志,若已取消则抛出 ActionCancelledError 在处理函数关键节点调用:ctx.check_cancel() """ if self.is_cancelled: raise ActionCancelledError( f"Action {self._action.type_key} 已被取消" ) return False # ── 共享数据存储 ────────────────────────────────────────────── def set(self, key: str, value: Any) -> None: """写入共享数据""" with self._lock: self._store[key] = value def get(self, key: str, default: Any = None) -> Any: """读取共享数据""" with self._lock: return self._store.get(key, default) def update(self, data: dict) -> None: with self._lock: self._store.update(data) @property def store(self) -> dict: with self._lock: return dict(self._store) # ───────────────────────────────────────────────────────────────── # 自定义异常 # ───────────────────────────────────────────────────────────────── class ActionCancelledError(Exception): """Action 被取消时抛出""" pass class ActionTimeoutError(Exception): """Action 执行超时时抛出""" pass