Repository navigation
fix: preserve persistent data in backups #10661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
|
|
||
| # 从共享常量模块导入 | ||
| from .constants import ( | ||
| EXCLUDED_MAIN_DB_MODELS, | ||
| KB_METADATA_MODELS, | ||
| MAIN_DB_MODELS, | ||
| get_backup_directories, | ||
|
|
@@ -471,6 +472,22 @@ async def import_all( | |
| except Exception as e: | ||
| result.add_warning(f"导入配置文件失败: {e}") | ||
|
|
||
| if "config/mcp_server.json" in zf.namelist(): | ||
| try: | ||
| mcp_config_path = ( | ||
| Path(get_astrbot_data_path()) / "mcp_server.json" | ||
| ) | ||
| mcp_config_path.parent.mkdir(parents=True, exist_ok=True) | ||
| if mcp_config_path.exists(): | ||
| shutil.copy2( | ||
| mcp_config_path, | ||
| mcp_config_path.with_suffix(".json.bak"), | ||
| ) | ||
| mcp_config_path.write_bytes(zf.read("config/mcp_server.json")) | ||
| result.imported_files["mcp_config"] = 1 | ||
| except Exception as e: | ||
| result.add_warning(f"Failed to restore MCP configuration: {e}") | ||
|
|
||
| if progress_callback: | ||
| await progress_callback("config", 100, 100, "配置文件导入完成") | ||
|
|
||
|
|
@@ -532,7 +549,10 @@ async def _clear_main_db(self) -> None: | |
| """清空主数据库所有表""" | ||
| async with self.main_db.get_db() as session: | ||
| async with session.begin(): | ||
| for table_name, model_class in MAIN_DB_MODELS.items(): | ||
| # Replace restores also invalidate device trust on the target instance. | ||
| for table_name, model_class in ( | ||
| MAIN_DB_MODELS | EXCLUDED_MAIN_DB_MODELS | ||
| ).items(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 High · Failed restores erase existing records When the process stops or database insertion fails after the clear commits and before the import transaction commits, Make clearing and importing the main database one transaction, or stage the restored data and swap it in only after the import succeeds. Prompt for AI agentsIn `astrbot/core/backup/importer.py` at line 555:
**Failed restores erase existing records**
When the process stops or database insertion fails after the clear commits and before the import transaction commits, `import_all` commits `_clear_main_db()` before `_import_main_database()` starts its separate transaction, so a crash or import failure between them leaves the newly registered tables empty along with the other cleared tables. The restore reports failure, but the target data is already lost.
Make clearing and importing the main database one transaction, or stage the restored data and swap it in only after the import succeeds. |
||
| try: | ||
| await session.execute(delete(model_class)) | ||
| logger.debug(f"已清空表 {table_name}") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟠 High · Database errors erase backed-up records
When a query for one of the newly registered tables fails,
_export_main_databasecatches a failed table query and records an empty list; a replace restore then clears that target table and imports no rows, while the backup and restore still report success.Propagate table export failures or mark the backup as incomplete so it cannot be mistaken for a complete backup.
Also at
astrbot/core/backup/constants.py:65-66.Prompt for AI agents