From d0b4b8bb8bcd2503f354bfa8ef6664a9d49f1b84 Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Tue, 23 Sep 2025 13:10:44 +0800 Subject: [PATCH] =?UTF-8?q?fix(plugin=5Fsystem):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=97=A0=E9=85=8D=E7=BD=AE=E6=8F=92=E4=BB=B6=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=97=B6=E4=BA=A7=E7=94=9F=E4=B8=8D=E5=BF=85=E8=A6=81=E8=AD=A6?= =?UTF-8?q?=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对于未定义 `config_schema` 的插件,现在会将其视作一种正常情况,并为其分配一个空的配置。 此举修复了先前版本中,这类插件在加载时会错误地触发“配置文件不存在”警告的问题。同时将生成默认配置文件的日志等级从 debug 调整为 info,使其在默认情况下可见。 --- src/common/database/db_migration.py | 64 ++++++++++++++++----------- src/plugin_system/base/plugin_base.py | 8 +++- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/common/database/db_migration.py b/src/common/database/db_migration.py index a1633d76c..b7f56abd9 100644 --- a/src/common/database/db_migration.py +++ b/src/common/database/db_migration.py @@ -1,7 +1,8 @@ # mmc/src/common/database/db_migration.py from sqlalchemy import inspect -from sqlalchemy.schema import AddColumn, CreateIndex +from sqlalchemy.schema import CreateIndex +from sqlalchemy.sql import text from src.common.database.sqlalchemy_models import Base, get_engine from src.common.logger import get_logger @@ -17,7 +18,7 @@ async def check_and_migrate_database(): - 自动为现有表创建缺失的索引。 """ logger.info("正在检查数据库结构并执行自动迁移...") - engine = await get_engine() + engine = get_engine() async with engine.connect() as connection: # 在同步上下文中运行inspector操作 @@ -66,20 +67,34 @@ async def check_and_migrate_database(): if missing_columns: logger.info(f"在表 '{table_name}' 中发现缺失的列: {', '.join(missing_columns)}") - async with connection.begin() as trans: + + def add_columns_sync(conn): + dialect = conn.dialect for column_name in missing_columns: - try: - column = table.c[column_name] - add_column_ddl = AddColumn(table_name, column) - await connection.execute(add_column_ddl) - logger.info(f"成功向表 '{table_name}' 添加列 '{column_name}'。") - except Exception as e: - logger.error( - f"向表 '{table_name}' 添加列 '{column_name}' 失败: {e}", - exc_info=True, - ) - await trans.rollback() - break # 如果一列失败,则停止处理此表的其他列 + column = table.c[column_name] + + # 使用DDLCompiler为特定方言编译列 + compiler = dialect.ddl_compiler(dialect, None) + + # 编译列的数据类型 + column_type = compiler.get_column_specification(column) + + # 构建原生SQL + sql = f"ALTER TABLE {table.name} ADD COLUMN {column.name} {column_type}" + + # 添加默认值(如果存在) + if column.default: + default_value = compiler.render_literal_value(column.default.arg, column.type) + sql += f" DEFAULT {default_value}" + + # 添加非空约束(如果存在) + if not column.nullable: + sql += " NOT NULL" + + conn.execute(text(sql)) + logger.info(f"成功向表 '{table_name}' 添加列 '{column_name}'。") + + await connection.run_sync(add_columns_sync) else: logger.info(f"表 '{table_name}' 的列结构一致。") @@ -92,20 +107,16 @@ async def check_and_migrate_database(): if missing_indexes: logger.info(f"在表 '{table_name}' 中发现缺失的索引: {', '.join(missing_indexes)}") - async with connection.begin() as trans: - for index_name in missing_indexes: - try: + + def add_indexes_sync(conn): + with conn.begin(): + for index_name in missing_indexes: index_obj = next((idx for idx in table.indexes if idx.name == index_name), None) if index_obj is not None: - await connection.execute(CreateIndex(index_obj)) + conn.execute(CreateIndex(index_obj)) logger.info(f"成功为表 '{table_name}' 创建索引 '{index_name}'。") - except Exception as e: - logger.error( - f"为表 '{table_name}' 创建索引 '{index_name}' 失败: {e}", - exc_info=True, - ) - await trans.rollback() - break # 如果一个索引失败,则停止处理此表的其他索引 + + await connection.run_sync(add_indexes_sync) else: logger.debug(f"表 '{table_name}' 的索引一致。") @@ -114,3 +125,4 @@ async def check_and_migrate_database(): continue logger.info("数据库结构检查与自动迁移完成。") + diff --git a/src/plugin_system/base/plugin_base.py b/src/plugin_system/base/plugin_base.py index fa5936b81..9ef95182d 100644 --- a/src/plugin_system/base/plugin_base.py +++ b/src/plugin_system/base/plugin_base.py @@ -215,7 +215,7 @@ class PluginBase(ABC): def _generate_and_save_default_config(self, config_file_path: str): """根据插件的Schema生成并保存默认配置文件""" if not self.config_schema: - logger.debug(f"{self.log_prefix} 插件未定义config_schema,不生成配置文件") + logger.info(f"{self.log_prefix} 插件未定义config_schema,不生成配置文件") return toml_str = f"# {self.plugin_name} - 自动生成的配置文件\n" @@ -479,6 +479,12 @@ class PluginBase(ABC): # 检查最终的用户配置文件是否存在 if not os.path.exists(user_config_path): + # 如果插件没有定义config_schema,那么不创建文件是正常行为 + if not self.config_schema: + logger.debug(f"{self.log_prefix} 插件未定义config_schema,使用空的配置.") + self.config = {} + return + logger.warning(f"{self.log_prefix} 用户配置文件 {user_config_path} 不存在且无法创建。") return