feat: 优化整体项目
This commit is contained in:
@@ -117,24 +117,107 @@ class PluginManager(metaclass=Singleton):
|
||||
if not found:
|
||||
logger.warning(f"未找到插件类 {plugin_name}")
|
||||
|
||||
def _resolve_load_order(self, plugin_classes: List[Type[PluginBase]]) -> List[Type[PluginBase]]:
|
||||
"""
|
||||
解析插件加载顺序(拓扑排序 + 优先级排序)
|
||||
|
||||
Args:
|
||||
plugin_classes: 插件类列表
|
||||
|
||||
Returns:
|
||||
按依赖关系和优先级排序后的插件类列表
|
||||
"""
|
||||
# 构建插件名到类的映射
|
||||
name_to_class = {cls.__name__: cls for cls in plugin_classes}
|
||||
|
||||
# 构建依赖图
|
||||
dependencies = {}
|
||||
for cls in plugin_classes:
|
||||
deps = getattr(cls, 'dependencies', [])
|
||||
dependencies[cls.__name__] = [d for d in deps if d in name_to_class]
|
||||
|
||||
# 拓扑排序
|
||||
sorted_names = []
|
||||
visited = set()
|
||||
temp_visited = set()
|
||||
|
||||
def visit(name: str):
|
||||
if name in temp_visited:
|
||||
# 检测到循环依赖
|
||||
logger.warning(f"检测到循环依赖: {name}")
|
||||
return
|
||||
if name in visited:
|
||||
return
|
||||
|
||||
temp_visited.add(name)
|
||||
|
||||
# 先访问依赖
|
||||
for dep in dependencies.get(name, []):
|
||||
visit(dep)
|
||||
|
||||
temp_visited.remove(name)
|
||||
visited.add(name)
|
||||
sorted_names.append(name)
|
||||
|
||||
# 按优先级排序后再进行拓扑排序
|
||||
priority_sorted = sorted(
|
||||
plugin_classes,
|
||||
key=lambda cls: getattr(cls, 'load_priority', 50),
|
||||
reverse=True
|
||||
)
|
||||
|
||||
for cls in priority_sorted:
|
||||
if cls.__name__ not in visited:
|
||||
visit(cls.__name__)
|
||||
|
||||
# 返回排序后的类列表
|
||||
return [name_to_class[name] for name in sorted_names if name in name_to_class]
|
||||
|
||||
async def load_plugins(self, load_disabled: bool = True) -> Union[List[str], bool]:
|
||||
"""加载所有插件(按依赖顺序)"""
|
||||
loaded_plugins = []
|
||||
|
||||
# 第一步:收集所有插件类
|
||||
all_plugin_classes = []
|
||||
plugin_disabled_map = {}
|
||||
|
||||
for dirname in os.listdir("plugins"):
|
||||
if os.path.isdir(f"plugins/{dirname}") and os.path.exists(f"plugins/{dirname}/main.py"):
|
||||
try:
|
||||
module = importlib.import_module(f"plugins.{dirname}.main")
|
||||
for name, obj in inspect.getmembers(module):
|
||||
if inspect.isclass(obj) and issubclass(obj, PluginBase) and obj != PluginBase:
|
||||
all_plugin_classes.append(obj)
|
||||
|
||||
# 记录是否禁用
|
||||
is_disabled = False
|
||||
if not load_disabled:
|
||||
is_disabled = obj.__name__ in self.excluded_plugins or dirname in self.excluded_plugins
|
||||
|
||||
if await self._load_plugin_class(obj, is_disabled=is_disabled):
|
||||
loaded_plugins.append(obj.__name__)
|
||||
plugin_disabled_map[obj.__name__] = is_disabled
|
||||
except:
|
||||
logger.error(f"加载 {dirname} 时发生错误: {traceback.format_exc()}")
|
||||
|
||||
# 第二步:按依赖顺序排序
|
||||
sorted_classes = self._resolve_load_order(all_plugin_classes)
|
||||
logger.info(f"插件加载顺序: {[cls.__name__ for cls in sorted_classes]}")
|
||||
|
||||
# 第三步:按顺序加载插件
|
||||
for plugin_class in sorted_classes:
|
||||
plugin_name = plugin_class.__name__
|
||||
is_disabled = plugin_disabled_map.get(plugin_name, False)
|
||||
|
||||
# 检查依赖是否已加载
|
||||
deps = getattr(plugin_class, 'dependencies', [])
|
||||
deps_satisfied = all(dep in self.plugins for dep in deps)
|
||||
|
||||
if not deps_satisfied and not is_disabled:
|
||||
missing_deps = [dep for dep in deps if dep not in self.plugins]
|
||||
logger.warning(f"插件 {plugin_name} 的依赖未满足: {missing_deps},跳过加载")
|
||||
continue
|
||||
|
||||
if await self._load_plugin_class(plugin_class, is_disabled=is_disabled):
|
||||
loaded_plugins.append(plugin_name)
|
||||
|
||||
return loaded_plugins
|
||||
|
||||
async def unload_plugin(self, plugin_name: str) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user