summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/ops.md8
-rw-r--r--src/db/mod.rs8
2 files changed, 13 insertions, 3 deletions
diff --git a/docs/ops.md b/docs/ops.md
index 8f21c79..02644c2 100644
--- a/docs/ops.md
+++ b/docs/ops.md
@@ -2,6 +2,10 @@
## Upgrades
-`hi` will automatically upgrade its database on startup. Before doing so, it will create a backup of your database (at `.hi.backup`, or controlled by `--backup-database-url`). If the migration process succeeds, this backup will be deleted automatically. If the migration process _fails_, however, the backup will be left in place. In addition, `hi` will attempt to restore your existing database from the backup before exiting.
+`hi` will automatically upgrade its database on startup. Before doing so, it will create a backup of your database (at `.hi.backup`, or controlled by `--backup-database-url`). If the migration process succeeds, this backup will be deleted automatically. If the migration process _fails_, however, `hi` will attempt to restore your existing database from the backup before exiting. If the restore process also fails, then both the backup database and the suspected-broken database will be left in place.
-`hi` will not start if the backup database already exists. To restart `hi` after a failure, move the backup database aside. Once you are satisfied that `hi` has recovered successfully, you can delete it. If you need to restore the database manually, you can also copy it overtop of your database using normal filesystem tools (`cp -a .hi.backup. hi`, for example).
+To avoid destroying backups that may still be needed, `hi` will not start if the backup database already exists. **There is no catch-all advice on how to proceed**, but you can try the following:
+
+* Start the server with **a copy** of the backup database, and determine if any data has been lost. If not, shut it down, replace your main database by copying the backup, and carry on.
+
+The `hi` database is an ordinary file. While the server is not running, it can be freely copied or renamed without invalidating the data in it.
diff --git a/src/db/mod.rs b/src/db/mod.rs
index bbaec7d..b9c59ef 100644
--- a/src/db/mod.rs
+++ b/src/db/mod.rs
@@ -28,6 +28,8 @@ pub async fn prepare(url: &str, backup_url: &str) -> Result<SqlitePool, Error> {
if let Err(migrate_error) = sqlx::migrate!().run(&pool).await {
if let Err(restore_error) = backup::Backup::from(&backup_pool).to(&pool).backup().await {
Err(Error::Restore(restore_error, migrate_error))?;
+ } else if let Err(drop_error) = Sqlite::drop_database(backup_url).await {
+ Err(Error::Drop(drop_error, migrate_error))?;
} else {
Err(migrate_error)?;
};
@@ -77,8 +79,12 @@ pub enum Error {
/// Failure due to a database backup error. See [`backup::Error`].
#[error(transparent)]
Backup(#[from] backup::Error),
- #[error("backing out failed migration also failed: {0} ({1})")]
+ #[error("migration failed: {1}\nrestoring backup failed: {0}")]
Restore(backup::Error, sqlx::migrate::MigrateError),
+ #[error(
+ "migration failed: {1}\nrestoring from backup succeeded, but deleting backup failed: {0}"
+ )]
+ Drop(sqlx::Error, sqlx::migrate::MigrateError),
/// Failure due to a database migration error. See
/// [`sqlx::migrate::MigrateError`].
#[error(transparent)]