205 lines
6.5 KiB
Python
205 lines
6.5 KiB
Python
"""插件桥接器 - 共享事件、广播、桥接"""
|
||
from typing import Any, Callable, Optional
|
||
from dataclasses import dataclass, field
|
||
|
||
from oss.logger.logger import Log
|
||
from oss.plugin.types import Plugin, register_plugin_type
|
||
|
||
|
||
@dataclass
|
||
class BridgeEvent:
|
||
"""桥接事件"""
|
||
type: str
|
||
source_plugin: str
|
||
payload: Any = None
|
||
context: dict[str, Any] = field(default_factory=dict)
|
||
|
||
|
||
class EventBus:
|
||
"""事件总线"""
|
||
|
||
def __init__(self):
|
||
self._handlers: dict[str, list[Callable]] = {}
|
||
self._history: list[BridgeEvent] = []
|
||
|
||
def emit(self, event: BridgeEvent):
|
||
"""发布事件"""
|
||
self._history.append(event)
|
||
handlers = self._handlers.get(event.type, [])
|
||
wildcard_handlers = self._handlers.get("*", [])
|
||
for handler in handlers + wildcard_handlers:
|
||
try:
|
||
handler(event)
|
||
except Exception:
|
||
pass
|
||
|
||
def on(self, event_type: str, handler: Callable):
|
||
"""订阅事件"""
|
||
if event_type not in self._handlers:
|
||
self._handlers[event_type] = []
|
||
self._handlers[event_type].append(handler)
|
||
|
||
def off(self, event_type: str, handler: Callable):
|
||
"""取消订阅"""
|
||
if event_type in self._handlers:
|
||
try:
|
||
self._handlers[event_type].remove(handler)
|
||
except ValueError:
|
||
pass
|
||
|
||
def once(self, event_type: str, handler: Callable):
|
||
"""仅触发一次"""
|
||
def wrapper(event):
|
||
self.off(event_type, wrapper)
|
||
handler(event)
|
||
self.on(event_type, wrapper)
|
||
|
||
def get_history(self, event_type: str = None) -> list[BridgeEvent]:
|
||
"""获取事件历史"""
|
||
if event_type:
|
||
return [e for e in self._history if e.type == event_type]
|
||
return self._history.copy()
|
||
|
||
def clear_history(self):
|
||
"""清空事件历史"""
|
||
self._history.clear()
|
||
|
||
|
||
class BroadcastManager:
|
||
"""广播管理器"""
|
||
|
||
def __init__(self, event_bus: EventBus):
|
||
self.event_bus = event_bus
|
||
self._channels: dict[str, list[str]] = {}
|
||
|
||
def create_channel(self, name: str, plugins: list[str]):
|
||
"""创建广播频道"""
|
||
self._channels[name] = plugins
|
||
|
||
def broadcast(self, channel: str, payload: Any, source_plugin: str = ""):
|
||
"""广播到指定频道"""
|
||
if channel not in self._channels:
|
||
return
|
||
event = BridgeEvent(
|
||
type=f"broadcast.{channel}",
|
||
source_plugin=source_plugin,
|
||
payload=payload
|
||
)
|
||
self.event_bus.emit(event)
|
||
|
||
def get_channels(self) -> dict[str, list[str]]:
|
||
"""获取所有频道"""
|
||
return self._channels.copy()
|
||
|
||
|
||
class ServiceRegistry:
|
||
"""服务注册表(RPC)"""
|
||
|
||
def __init__(self):
|
||
self._services: dict[str, dict[str, Callable]] = {}
|
||
|
||
def register(self, plugin_name: str, service_name: str, handler: Callable):
|
||
"""注册服务"""
|
||
if plugin_name not in self._services:
|
||
self._services[plugin_name] = {}
|
||
self._services[plugin_name][service_name] = handler
|
||
|
||
def unregister(self, plugin_name: str, service_name: str = None):
|
||
"""注销服务"""
|
||
if plugin_name in self._services:
|
||
if service_name:
|
||
self._services[plugin_name].pop(service_name, None)
|
||
else:
|
||
del self._services[plugin_name]
|
||
|
||
def call(self, plugin_name: str, service_name: str, *args, **kwargs) -> Any:
|
||
"""远程调用"""
|
||
if plugin_name not in self._services:
|
||
raise RuntimeError(f"插件 '{plugin_name}' 未注册服务")
|
||
if service_name not in self._services[plugin_name]:
|
||
raise RuntimeError(f"插件 '{plugin_name}' 未注册服务 '{service_name}'")
|
||
return self._services[plugin_name][service_name](*args, **kwargs)
|
||
|
||
def list_services(self, plugin_name: str = None) -> dict[str, dict[str, Callable]]:
|
||
"""列出服务"""
|
||
if plugin_name:
|
||
return self._services.get(plugin_name, {}).copy()
|
||
return {k: v.copy() for k, v in self._services.items()}
|
||
|
||
|
||
class BridgeManager:
|
||
"""桥接管理器"""
|
||
|
||
def __init__(self, event_bus: EventBus):
|
||
self.event_bus = event_bus
|
||
self._bridges: dict[str, dict[str, Any]] = {}
|
||
|
||
def create_bridge(self, name: str, from_plugin: str, to_plugin: str, event_mapping: dict[str, str]):
|
||
"""创建桥接:将 from_plugin 的事件映射到 to_plugin"""
|
||
self._bridges[name] = {
|
||
"from": from_plugin,
|
||
"to": to_plugin,
|
||
"mapping": event_mapping,
|
||
}
|
||
# 注册桥接处理器
|
||
for src_event, dst_event in event_mapping.items():
|
||
def handler(event, dst_event=dst_event):
|
||
bridged = BridgeEvent(
|
||
type=dst_event,
|
||
source_plugin=event.source_plugin,
|
||
payload=event.payload,
|
||
context={**event.context, "_bridged_from": event.type}
|
||
)
|
||
self.event_bus.emit(bridged)
|
||
self.event_bus.on(src_event, handler)
|
||
|
||
def remove_bridge(self, name: str):
|
||
"""移除桥接"""
|
||
if name in self._bridges:
|
||
del self._bridges[name]
|
||
|
||
def get_bridges(self) -> dict[str, dict[str, Any]]:
|
||
"""获取所有桥接"""
|
||
return self._bridges.copy()
|
||
|
||
|
||
class PluginBridgePlugin(Plugin):
|
||
"""插件桥接器插件"""
|
||
|
||
def __init__(self):
|
||
self.event_bus = EventBus()
|
||
self.broadcast = None
|
||
self.bridge = None
|
||
self.services = ServiceRegistry()
|
||
self.storage = None # 共享存储接口
|
||
|
||
def init(self, deps: dict = None):
|
||
"""初始化"""
|
||
self.broadcast = BroadcastManager(self.event_bus)
|
||
self.bridge = BridgeManager(self.event_bus)
|
||
|
||
def start(self):
|
||
"""启动"""
|
||
Log.info("plugin-bridge", "事件总线、广播、桥接、RPC、共享存储已启动")
|
||
|
||
def stop(self):
|
||
"""停止"""
|
||
self.event_bus.clear_history()
|
||
|
||
def set_plugin_storage(self, storage_plugin):
|
||
"""设置存储插件引用"""
|
||
if storage_plugin:
|
||
self.storage = storage_plugin.get_shared()
|
||
|
||
|
||
# 注册类型
|
||
register_plugin_type("BridgeEvent", BridgeEvent)
|
||
register_plugin_type("EventBus", EventBus)
|
||
register_plugin_type("BroadcastManager", BroadcastManager)
|
||
register_plugin_type("BridgeManager", BridgeManager)
|
||
register_plugin_type("ServiceRegistry", ServiceRegistry)
|
||
|
||
|
||
def New():
|
||
return PluginBridgePlugin()
|