Files
NebulaShell/store/@{FutureOSS}/plugin-bridge/main.py
Falck 76147bae94 初始提交 - FutureOSS v1.0 插件化运行时框架
一切皆为插件的开发者工具运行时框架

🧩 核心特性:
  - 插件热插拔 (importlib 动态加载)
  - 依赖自动解析 (拓扑排序 + 循环检测)
  - 企业级稳定 (熔断/降级/重试/隔离)
  - 事件驱动 (发布/订阅事件总线)
  - 完整配置 (YAML 配置 + 热重载)
2026-04-06 09:57:10 +08:00

204 lines
6.4 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.
"""插件桥接器 - 共享事件、广播、桥接"""
from typing import Any, Callable, Optional
from dataclasses import dataclass, field
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):
"""启动"""
print("[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()