feat: 优化整体项目

This commit is contained in:
2025-12-05 18:06:13 +08:00
parent b4df26f61d
commit 7d3ef70093
13 changed files with 2661 additions and 305 deletions

View File

@@ -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: