mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-31 12:14:44 -04:00
Backup on Migrations (#898)
* Refactored how the migrations are run. * A backup will be performed before any migrations. Added additional guards before a sub-module is loaded.
This commit is contained in:
parent
2bf1b96411
commit
027b8b78e2
@ -36,7 +36,6 @@ namespace API
|
|||||||
var isDocker = new OsInfo(Array.Empty<IOsVersionAdapter>()).IsDocker;
|
var isDocker = new OsInfo(Array.Empty<IOsVersionAdapter>()).IsDocker;
|
||||||
|
|
||||||
|
|
||||||
// TODO: Figure out a solution for this migration and logger.
|
|
||||||
var directoryService = new DirectoryService(null, new FileSystem());
|
var directoryService = new DirectoryService(null, new FileSystem());
|
||||||
MigrateConfigFiles.Migrate(isDocker, directoryService);
|
MigrateConfigFiles.Migrate(isDocker, directoryService);
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ namespace API
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var context = services.GetRequiredService<DataContext>();
|
var context = services.GetRequiredService<DataContext>();
|
||||||
var roleManager = services.GetRequiredService<RoleManager<AppRole>>();
|
|
||||||
|
|
||||||
if (isDocker && new FileInfo("data/appsettings.json").Exists)
|
if (isDocker && new FileInfo("data/appsettings.json").Exists)
|
||||||
{
|
{
|
||||||
@ -81,28 +80,27 @@ namespace API
|
|||||||
requiresCoverImageMigration = false;
|
requiresCoverImageMigration = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Apply all migrations on startup
|
|
||||||
// If we have pending migrations, make a backup first
|
|
||||||
var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
|
|
||||||
if (pendingMigrations.Any())
|
|
||||||
{
|
|
||||||
var logger = services.GetRequiredService<ILogger<Program>>();
|
|
||||||
logger.LogInformation("Performing backup as migrations are needed");
|
|
||||||
// var backupService = services.GetRequiredService<BackupService>();
|
|
||||||
// await backupService.BackupDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
await context.Database.MigrateAsync();
|
|
||||||
|
|
||||||
if (requiresCoverImageMigration)
|
if (requiresCoverImageMigration)
|
||||||
{
|
{
|
||||||
await MigrateCoverImages.UpdateDatabaseWithImages(context, directoryService);
|
await MigrateCoverImages.UpdateDatabaseWithImages(context, directoryService);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Seed.SeedRoles(roleManager);
|
// // Apply all migrations on startup
|
||||||
await Seed.SeedSettings(context, directoryService);
|
// // If we have pending migrations, make a backup first
|
||||||
await Seed.SeedUserApiKeys(context);
|
// var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
|
||||||
|
// if (pendingMigrations.Any())
|
||||||
|
// {
|
||||||
|
// var logger = services.GetRequiredService<ILogger<Program>>();
|
||||||
|
// logger.LogInformation("Performing backup as migrations are needed");
|
||||||
|
// // var backupService = services.GetRequiredService<BackupService>();
|
||||||
|
// // await backupService.BackupDatabase();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// await context.Database.MigrateAsync();
|
||||||
|
//
|
||||||
|
// await Seed.SeedRoles(roleManager);
|
||||||
|
// await Seed.SeedSettings(context, directoryService);
|
||||||
|
// await Seed.SeedUserApiKeys(context);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -6,10 +6,12 @@ using System.Net;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using API.Data;
|
using API.Data;
|
||||||
|
using API.Entities;
|
||||||
using API.Extensions;
|
using API.Extensions;
|
||||||
using API.Middleware;
|
using API.Middleware;
|
||||||
using API.Services;
|
using API.Services;
|
||||||
using API.Services.HostedServices;
|
using API.Services.HostedServices;
|
||||||
|
using API.Services.Tasks;
|
||||||
using API.SignalR;
|
using API.SignalR;
|
||||||
using Hangfire;
|
using Hangfire;
|
||||||
using Hangfire.MemoryStorage;
|
using Hangfire.MemoryStorage;
|
||||||
@ -19,8 +21,10 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.ResponseCompression;
|
using Microsoft.AspNetCore.ResponseCompression;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
@ -130,12 +134,45 @@ namespace API
|
|||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IWebHostEnvironment env,
|
public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IWebHostEnvironment env,
|
||||||
IHostApplicationLifetime applicationLifetime, IServiceProvider serviceProvider, ICacheService cacheService,
|
IHostApplicationLifetime applicationLifetime, IServiceProvider serviceProvider, ICacheService cacheService,
|
||||||
IDirectoryService directoryService, IUnitOfWork unitOfWork)
|
IDirectoryService directoryService, IUnitOfWork unitOfWork, IBackupService backupService)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Apply Migrations
|
// Apply Migrations
|
||||||
Task.Run(async () => await MigrateBookmarks.Migrate(directoryService, unitOfWork,
|
try
|
||||||
serviceProvider.GetRequiredService<ILogger<Program>>(), cacheService)).GetAwaiter().GetResult();
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
// Apply all migrations on startup
|
||||||
|
// If we have pending migrations, make a backup first
|
||||||
|
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
|
||||||
|
var context = serviceProvider.GetRequiredService<DataContext>();
|
||||||
|
var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
|
||||||
|
if (pendingMigrations.Any())
|
||||||
|
{
|
||||||
|
logger.LogInformation("Performing backup as migrations are needed");
|
||||||
|
await backupService.BackupDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.Database.MigrateAsync();
|
||||||
|
|
||||||
|
await MigrateBookmarks.Migrate(directoryService, unitOfWork,
|
||||||
|
logger, cacheService);
|
||||||
|
|
||||||
|
var roleManager = serviceProvider.GetRequiredService<RoleManager<AppRole>>();
|
||||||
|
|
||||||
|
await Seed.SeedRoles(roleManager);
|
||||||
|
await Seed.SeedSettings(context, directoryService);
|
||||||
|
await Seed.SeedUserApiKeys(context);
|
||||||
|
|
||||||
|
}).GetAwaiter()
|
||||||
|
.GetResult();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
|
||||||
|
logger.LogCritical(ex, "An error occurred during migration");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.UseMiddleware<ExceptionMiddleware>();
|
app.UseMiddleware<ExceptionMiddleware>();
|
||||||
|
@ -10,6 +10,7 @@ import { LibraryAccessGuard } from './_guards/library-access.guard';
|
|||||||
import { OnDeckComponent } from './on-deck/on-deck.component';
|
import { OnDeckComponent } from './on-deck/on-deck.component';
|
||||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||||
import { AllSeriesComponent } from './all-series/all-series.component';
|
import { AllSeriesComponent } from './all-series/all-series.component';
|
||||||
|
import { AdminGuard } from './_guards/admin.guard';
|
||||||
|
|
||||||
// TODO: Once we modularize the components, use this and measure performance impact: https://angular.io/guide/lazy-loading-ngmodules#preloading-modules
|
// TODO: Once we modularize the components, use this and measure performance impact: https://angular.io/guide/lazy-loading-ngmodules#preloading-modules
|
||||||
|
|
||||||
@ -17,18 +18,22 @@ const routes: Routes = [
|
|||||||
{path: '', component: UserLoginComponent},
|
{path: '', component: UserLoginComponent},
|
||||||
{
|
{
|
||||||
path: 'admin',
|
path: 'admin',
|
||||||
|
canActivate: [AdminGuard],
|
||||||
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
|
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'collections',
|
path: 'collections',
|
||||||
|
canActivate: [AuthGuard],
|
||||||
loadChildren: () => import('./collections/collections.module').then(m => m.CollectionsModule)
|
loadChildren: () => import('./collections/collections.module').then(m => m.CollectionsModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'preferences',
|
path: 'preferences',
|
||||||
|
canActivate: [AuthGuard],
|
||||||
loadChildren: () => import('./user-settings/user-settings.module').then(m => m.UserSettingsModule)
|
loadChildren: () => import('./user-settings/user-settings.module').then(m => m.UserSettingsModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'lists',
|
path: 'lists',
|
||||||
|
canActivate: [AuthGuard],
|
||||||
loadChildren: () => import('./reading-list/reading-list.module').then(m => m.ReadingListModule)
|
loadChildren: () => import('./reading-list/reading-list.module').then(m => m.ReadingListModule)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user