155 lines
5.7 KiB
Python
155 lines
5.7 KiB
Python
# -*- 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 |