diff --git a/API/API.csproj b/API/API.csproj index fbf15067e..759f1ae86 100644 --- a/API/API.csproj +++ b/API/API.csproj @@ -49,13 +49,13 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/API/Program.cs b/API/Program.cs index 4ed8ce56a..286a0f0cd 100644 --- a/API/Program.cs +++ b/API/Program.cs @@ -62,7 +62,15 @@ namespace API if (pendingMigrations.Any()) { logger.LogInformation("Performing backup as migrations are needed. Backup will be kavita.db in temp folder"); - directoryService.CopyFileToDirectory(directoryService.FileSystem.Path.Join(directoryService.ConfigDirectory, "kavita.db"), directoryService.TempDirectory); + var migrationDirectory = await GetMigrationDirectory(context, directoryService); + directoryService.ExistOrCreate(migrationDirectory); + + if (!directoryService.FileSystem.File.Exists( + directoryService.FileSystem.Path.Join(migrationDirectory, "kavita.db"))) + { + directoryService.CopyFileToDirectory(directoryService.FileSystem.Path.Join(directoryService.ConfigDirectory, "kavita.db"), migrationDirectory); + logger.LogInformation("Database backed up to {MigrationDirectory}", migrationDirectory); + } } await context.Database.MigrateAsync(); @@ -82,12 +90,42 @@ namespace API catch (Exception ex) { var logger = services.GetRequiredService>(); - logger.LogCritical(ex, "An error occurred during migration"); + var context = services.GetRequiredService(); + var migrationDirectory = await GetMigrationDirectory(context, directoryService); + + logger.LogCritical(ex, "A migration failed during startup. Restoring backup from {MigrationDirectory} and exiting", migrationDirectory); + directoryService.CopyFileToDirectory(directoryService.FileSystem.Path.Join(migrationDirectory, "kavita.db"), directoryService.ConfigDirectory); + + return; } await host.RunAsync(); } + private static async Task GetMigrationDirectory(DataContext context, IDirectoryService directoryService) + { + string currentVersion = null; + try + { + currentVersion = + (await context.ServerSetting.SingleOrDefaultAsync(s => + s.Key == ServerSettingKey.InstallVersion))?.Value; + } + catch + { + // ignored + } + + if (string.IsNullOrEmpty(currentVersion)) + { + currentVersion = "vUnknown"; + } + + var migrationDirectory = directoryService.FileSystem.Path.Join(directoryService.TempDirectory, + "migration", currentVersion); + return migrationDirectory; + } + private static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) =>