⚡ 初始提交 - FutureOSS v1.0 插件化运行时框架
一切皆为插件的开发者工具运行时框架
🧩 核心特性:
- 插件热插拔 (importlib 动态加载)
- 依赖自动解析 (拓扑排序 + 循环检测)
- 企业级稳定 (熔断/降级/重试/隔离)
- 事件驱动 (发布/订阅事件总线)
- 完整配置 (YAML 配置 + 热重载)
This commit is contained in:
39
store/@{FutureOSS}/dependency/README.md
Normal file
39
store/@{FutureOSS}/dependency/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# dependency 依赖解析
|
||||
|
||||
插件依赖关系管理,使用拓扑排序确定加载顺序。
|
||||
|
||||
## 功能
|
||||
|
||||
- 拓扑排序(Kahn 算法)
|
||||
- 循环依赖检测(DFS)
|
||||
- 缺失依赖检测
|
||||
- 自动按依赖顺序加载插件
|
||||
|
||||
## 使用
|
||||
|
||||
```python
|
||||
dep = dependency_plugin
|
||||
|
||||
# 添加插件及其依赖
|
||||
dep.add_plugin("plugin-a", ["plugin-b", "plugin-c"])
|
||||
dep.add_plugin("plugin-b", [])
|
||||
dep.add_plugin("plugin-c", ["plugin-b"])
|
||||
|
||||
# 解析依赖顺序
|
||||
order = dep.resolve() # 返回 ["plugin-b", "plugin-c", "plugin-a"]
|
||||
|
||||
# 检查缺失依赖
|
||||
missing = dep.get_missing_deps()
|
||||
|
||||
# 获取加载顺序
|
||||
order = dep.get_order()
|
||||
```
|
||||
|
||||
## manifest.json 声明
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {...},
|
||||
"dependencies": ["lifecycle", "circuit-breaker"]
|
||||
}
|
||||
```
|
||||
BIN
store/@{FutureOSS}/dependency/__pycache__/main.cpython-313.pyc
Normal file
BIN
store/@{FutureOSS}/dependency/__pycache__/main.cpython-313.pyc
Normal file
Binary file not shown.
138
store/@{FutureOSS}/dependency/main.py
Normal file
138
store/@{FutureOSS}/dependency/main.py
Normal file
@@ -0,0 +1,138 @@
|
||||
"""依赖解析插件 - 拓扑排序 + 循环依赖检测"""
|
||||
from typing import Any, Optional
|
||||
|
||||
from oss.plugin.types import Plugin, register_plugin_type
|
||||
|
||||
|
||||
class DependencyError(Exception):
|
||||
"""依赖错误"""
|
||||
pass
|
||||
|
||||
|
||||
class DependencyResolver:
|
||||
"""依赖解析器"""
|
||||
|
||||
def __init__(self):
|
||||
self.graph: dict[str, list[str]] = {} # 插件名 -> 依赖列表
|
||||
|
||||
def add_plugin(self, name: str, dependencies: list[str]):
|
||||
"""添加插件及其依赖"""
|
||||
self.graph[name] = dependencies
|
||||
|
||||
def resolve(self) -> list[str]:
|
||||
"""解析依赖,返回拓扑排序后的插件列表
|
||||
|
||||
例如:A 依赖 B,B 依赖 C
|
||||
图: A -> [B], B -> [C], C -> []
|
||||
结果: [C, B, A] (先启动没有依赖的,再启动依赖它们的)
|
||||
"""
|
||||
# 检测循环依赖
|
||||
self._detect_cycles()
|
||||
|
||||
# 拓扑排序 (Kahn 算法 - 反向)
|
||||
# in_degree[name] = name 依赖的插件数量
|
||||
in_degree: dict[str, int] = {name: 0 for name in self.graph}
|
||||
# 反向图: who_depends_on[dep] = [name1, name2, ...] (谁依赖 dep)
|
||||
who_depends_on: dict[str, list[str]] = {name: [] for name in self.graph}
|
||||
|
||||
for name, deps in self.graph.items():
|
||||
for dep in deps:
|
||||
if dep in in_degree:
|
||||
in_degree[name] += 1 # name 依赖 dep,所以 name 的入度 +1
|
||||
who_depends_on[dep].append(name) # dep 被 name 依赖
|
||||
|
||||
# 从没有依赖的插件开始
|
||||
queue = [name for name, degree in in_degree.items() if degree == 0]
|
||||
result = []
|
||||
|
||||
while queue:
|
||||
node = queue.pop(0)
|
||||
result.append(node)
|
||||
# node 已启动,减少依赖它的插件的入度
|
||||
for dependent in who_depends_on.get(node, []):
|
||||
in_degree[dependent] -= 1
|
||||
if in_degree[dependent] == 0:
|
||||
queue.append(dependent)
|
||||
|
||||
if len(result) != len(self.graph):
|
||||
raise DependencyError("无法解析依赖,可能存在循环依赖")
|
||||
|
||||
return result
|
||||
|
||||
def _detect_cycles(self):
|
||||
"""检测循环依赖"""
|
||||
visited = set()
|
||||
rec_stack = set()
|
||||
|
||||
def dfs(node: str) -> bool:
|
||||
visited.add(node)
|
||||
rec_stack.add(node)
|
||||
|
||||
for dep in self.graph.get(node, []):
|
||||
if dep not in visited:
|
||||
if dfs(dep):
|
||||
return True
|
||||
elif dep in rec_stack:
|
||||
raise DependencyError(f"检测到循环依赖: {node} -> {dep}")
|
||||
|
||||
rec_stack.remove(node)
|
||||
return False
|
||||
|
||||
for node in self.graph:
|
||||
if node not in visited:
|
||||
if dfs(node):
|
||||
raise DependencyError(f"检测到循环依赖涉及: {node}")
|
||||
|
||||
def get_missing(self) -> list[str]:
|
||||
"""获取缺失的依赖"""
|
||||
all_deps = set()
|
||||
for deps in self.graph.values():
|
||||
all_deps.update(deps)
|
||||
all_plugins = set(self.graph.keys())
|
||||
return list(all_deps - all_plugins)
|
||||
|
||||
|
||||
class DependencyPlugin(Plugin):
|
||||
"""依赖解析插件"""
|
||||
|
||||
def __init__(self):
|
||||
self.resolver = DependencyResolver()
|
||||
self.plugin_deps: dict[str, list[str]] = {}
|
||||
|
||||
def init(self, deps: dict = None):
|
||||
"""初始化"""
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
"""启动"""
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
"""停止"""
|
||||
pass
|
||||
|
||||
def add_plugin(self, name: str, dependencies: list[str]):
|
||||
"""添加插件及其依赖"""
|
||||
self.plugin_deps[name] = dependencies
|
||||
self.resolver.add_plugin(name, dependencies)
|
||||
|
||||
def resolve(self) -> list[str]:
|
||||
"""解析依赖顺序"""
|
||||
return self.resolver.resolve()
|
||||
|
||||
def get_missing_deps(self) -> list[str]:
|
||||
"""获取缺失的依赖"""
|
||||
return self.resolver.get_missing()
|
||||
|
||||
def get_order(self) -> list[str]:
|
||||
"""获取插件加载顺序"""
|
||||
return self.resolve()
|
||||
|
||||
|
||||
# 注册类型
|
||||
register_plugin_type("DependencyResolver", DependencyResolver)
|
||||
register_plugin_type("DependencyError", DependencyError)
|
||||
|
||||
|
||||
def New():
|
||||
return DependencyPlugin()
|
||||
15
store/@{FutureOSS}/dependency/manifest.json
Normal file
15
store/@{FutureOSS}/dependency/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"metadata": {
|
||||
"name": "dependency",
|
||||
"version": "1.0.0",
|
||||
"author": "FutureOSS",
|
||||
"description": "依赖解析 - 拓扑排序 + 循环依赖检测",
|
||||
"type": "core"
|
||||
},
|
||||
"config": {
|
||||
"enabled": true,
|
||||
"args": {}
|
||||
},
|
||||
"dependencies": [],
|
||||
"permissions": []
|
||||
}
|
||||
Reference in New Issue
Block a user