Fix backup not written to correct directory (#13853)

* Fix backup not written to correct directory

* Improve restore handling and only restore on actual error

* Fix first failed migration not causing a rollback
This commit is contained in:
JPVenson 2025-04-07 16:59:00 +02:00 committed by GitHub
parent e1ef4290af
commit 04ca27ad07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 7 deletions

View file

@ -149,11 +149,18 @@ namespace Jellyfin.Server.Migrations
} }
} }
List<IMigrationRoutine> databaseMigrations = [];
try try
{ {
foreach (var migrationRoutine in migrationsToBeApplied) foreach (var migrationRoutine in migrationsToBeApplied)
{ {
logger.LogInformation("Applying migration '{Name}'", migrationRoutine.Name); logger.LogInformation("Applying migration '{Name}'", migrationRoutine.Name);
var isDbMigration = migrationRoutine is IDatabaseMigrationRoutine;
if (isDbMigration)
{
databaseMigrations.Add(migrationRoutine);
}
try try
{ {
@ -167,17 +174,31 @@ namespace Jellyfin.Server.Migrations
// Mark the migration as completed // Mark the migration as completed
logger.LogInformation("Migration '{Name}' applied successfully", migrationRoutine.Name); logger.LogInformation("Migration '{Name}' applied successfully", migrationRoutine.Name);
migrationOptions.Applied.Add((migrationRoutine.Id, migrationRoutine.Name)); if (!isDbMigration)
saveConfiguration(migrationOptions); {
logger.LogDebug("Migration '{Name}' marked as applied in configuration.", migrationRoutine.Name); migrationOptions.Applied.Add((migrationRoutine.Id, migrationRoutine.Name));
saveConfiguration(migrationOptions);
logger.LogDebug("Migration '{Name}' marked as applied in configuration.", migrationRoutine.Name);
}
} }
} }
catch (System.Exception) when (migrationKey is not null && jellyfinDatabaseProvider is not null) catch (Exception) when (migrationKey is not null && jellyfinDatabaseProvider is not null)
{ {
logger.LogInformation("Rollback on database as migration reported failure."); if (databaseMigrations.Count != 0)
await jellyfinDatabaseProvider.RestoreBackupFast(migrationKey, CancellationToken.None).ConfigureAwait(false); {
logger.LogInformation("Rolling back database as migrations reported failure.");
await jellyfinDatabaseProvider.RestoreBackupFast(migrationKey, CancellationToken.None).ConfigureAwait(false);
}
throw; throw;
} }
foreach (var migrationRoutine in databaseMigrations)
{
migrationOptions.Applied.Add((migrationRoutine.Id, migrationRoutine.Name));
saveConfiguration(migrationOptions);
logger.LogDebug("Migration '{Name}' marked as applied in configuration.", migrationRoutine.Name);
}
} }
} }
} }

View file

@ -98,7 +98,7 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
Directory.CreateDirectory(backupFile); Directory.CreateDirectory(backupFile);
} }
backupFile = Path.Combine(_applicationPaths.DataPath, $"{key}_jellyfin.db"); backupFile = Path.Combine(backupFile, $"{key}_jellyfin.db");
File.Copy(path, backupFile); File.Copy(path, backupFile);
return Task.FromResult(key); return Task.FromResult(key);
} }
@ -106,6 +106,8 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
/// <inheritdoc /> /// <inheritdoc />
public Task RestoreBackupFast(string key, CancellationToken cancellationToken) public Task RestoreBackupFast(string key, CancellationToken cancellationToken)
{ {
// ensure there are absolutly no dangling Sqlite connections.
SqliteConnection.ClearAllPools();
var path = Path.Combine(_applicationPaths.DataPath, "jellyfin.db"); var path = Path.Combine(_applicationPaths.DataPath, "jellyfin.db");
var backupFile = Path.Combine(_applicationPaths.DataPath, BackupFolderName, $"{key}_jellyfin.db"); var backupFile = Path.Combine(_applicationPaths.DataPath, BackupFolderName, $"{key}_jellyfin.db");