159 lines
6.1 KiB
Python
159 lines
6.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Action 工厂注册表
|
||
─────────────────────────────────────────────────────────────────
|
||
将 ActionType → handler 函数的映射集中管理
|
||
支持:
|
||
- 内置 handler 自动注册
|
||
- 运行时动态注册/覆盖 handler
|
||
- 通过 create() 工厂方法快速创建 Action 实例
|
||
─────────────────────────────────────────────────────────────────
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
import threading
|
||
from typing import Callable, Dict, List, Optional, Union
|
||
|
||
from uas.action.action_model import Action, make_action
|
||
from uas.action.action_type import ActionType
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class ActionFactory:
|
||
"""
|
||
Action 工厂(单例)
|
||
─────────────────────────────────────────────────────────────
|
||
使用方式:
|
||
factory = ActionFactory.instance()
|
||
|
||
# 注册自定义 handler
|
||
factory.register(ActionType.CAPTURE_PHOTO, my_photo_handler)
|
||
|
||
# 创建 Action 实例(自动绑定 handler)
|
||
action = factory.create(
|
||
ActionType.CAPTURE_PHOTO,
|
||
source = "camera-01",
|
||
resolution = "4K",
|
||
format = "jpg",
|
||
)
|
||
─────────────────────────────────────────────────────────────
|
||
"""
|
||
|
||
_instance = None
|
||
_lock = threading.Lock()
|
||
|
||
@classmethod
|
||
def instance(cls) -> "ActionFactory":
|
||
if cls._instance is None:
|
||
cls._instance = cls()
|
||
return cls._instance
|
||
|
||
def __init__(self):
|
||
# { type_key: handler_fn }
|
||
self._handlers: Dict[str, Callable] = {}
|
||
self._init_builtin()
|
||
|
||
def _init_builtin(self):
|
||
"""自动注册所有内置 handler"""
|
||
from uas.action.actions.builtin_actions import BUILTIN_HANDLERS
|
||
for action_type, handler in BUILTIN_HANDLERS.items():
|
||
self.register(action_type, handler)
|
||
logger.info(f"✅ ActionFactory 初始化,内置 handler={len(self._handlers)}")
|
||
|
||
# ── 注册 ──────────────────────────────────────────────────────
|
||
|
||
def register(
|
||
self,
|
||
action_type: Union[ActionType, str],
|
||
handler: Callable,
|
||
override: bool = True,
|
||
) -> None:
|
||
"""
|
||
注册 Action 处理函数
|
||
:param action_type: ActionType 枚举 或 自定义字符串
|
||
:param handler: fn(action: Action, ctx: ActionContext) -> Any
|
||
:param override: True=允许覆盖已有 handler
|
||
"""
|
||
key = action_type.value if isinstance(action_type, ActionType) else str(action_type)
|
||
with self._lock:
|
||
if key in self._handlers and not override:
|
||
logger.warning(f"handler 已存在且 override=False,跳过: {key}")
|
||
return
|
||
self._handlers[key] = handler
|
||
logger.info(f"注册 handler: {key} -> {handler.__name__}")
|
||
|
||
def unregister(self, action_type: Union[ActionType, str]) -> bool:
|
||
"""注销 handler"""
|
||
key = action_type.value if isinstance(action_type, ActionType) else str(action_type)
|
||
with self._lock:
|
||
if key in self._handlers:
|
||
del self._handlers[key]
|
||
logger.info(f"注销 handler: {key}")
|
||
return True
|
||
return False
|
||
|
||
def get_handler(self, action_type: Union[ActionType, str]) -> Optional[Callable]:
|
||
"""获取指定类型的 handler"""
|
||
key = action_type.value if isinstance(action_type, ActionType) else str(action_type)
|
||
return self._handlers.get(key)
|
||
|
||
def has_handler(self, action_type: Union[ActionType, str]) -> bool:
|
||
key = action_type.value if isinstance(action_type, ActionType) else str(action_type)
|
||
return key in self._handlers
|
||
|
||
def registered_types(self) -> List[str]:
|
||
return list(self._handlers.keys())
|
||
|
||
# ── 工厂创建 ──────────────────────────────────────────────────
|
||
|
||
def create(
|
||
self,
|
||
action_type: Union[ActionType, str],
|
||
source: str = "system",
|
||
priority: int = 0,
|
||
handler: Optional[Callable] = None,
|
||
**params
|
||
) -> Action:
|
||
"""
|
||
工厂方法:创建并自动绑定 handler 的 Action 实例
|
||
:param action_type: 行为类型
|
||
:param source: 触发来源
|
||
:param priority: 执行优先级
|
||
:param handler: 若指定则覆盖注册表中的 handler
|
||
:param params: 传递给 Action 的业务参数
|
||
:return: Action 实例
|
||
"""
|
||
resolved_handler = handler or self.get_handler(action_type)
|
||
if resolved_handler is None:
|
||
logger.warning(f"未找到 handler: {action_type},将使用空处理器")
|
||
resolved_handler = _noop_handler
|
||
|
||
action = make_action(
|
||
action_type = action_type,
|
||
handler = resolved_handler,
|
||
source = source,
|
||
priority = priority,
|
||
**params,
|
||
)
|
||
logger.debug(f"创建 Action: {action}")
|
||
return action
|
||
|
||
def create_batch(self, specs: List[dict]) -> List[Action]:
|
||
"""
|
||
批量创建 Action
|
||
:param specs: [{"action_type": ..., "source": ..., **params}, ...]
|
||
"""
|
||
return [self.create(**spec) for spec in specs]
|
||
|
||
|
||
def _noop_handler(action, ctx):
|
||
"""空处理器(未注册 handler 时的占位)"""
|
||
logger.warning(f"[noop] Action [{action.type_key}] 无处理器,跳过执行")
|
||
return None
|
||
|
||
|
||
# 全局工厂实例
|
||
action_factory = ActionFactory.instance() |