feat: migrate runtime to postgresql
This commit is contained in:
@@ -21,12 +21,12 @@ using LiveRecorder.Infrastructure.Platforms.Douyin.Signing;
|
||||
using LiveRecorder.Infrastructure.Platforms.Huya;
|
||||
using LiveRecorder.Infrastructure.Services;
|
||||
using LiveRecorder.WebApi.Middleware;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var resetRecordingData = args.Contains("--reset-recording-data", StringComparer.OrdinalIgnoreCase);
|
||||
var migrateSqlitePath = GetOptionValue(args, "--migrate-sqlite");
|
||||
var corsOrigins = builder.Configuration.GetSection("Cors:Origins").Get<string[]>() ?? ["http://localhost:5173"];
|
||||
|
||||
builder.Services.AddControllers();
|
||||
@@ -111,16 +111,12 @@ builder.Services.AddHttpClient("bilibili", client =>
|
||||
}
|
||||
});
|
||||
|
||||
var sqliteConnectionStringBuilder = new SqliteConnectionStringBuilder(
|
||||
builder.Configuration.GetConnectionString("DefaultConnection"))
|
||||
{
|
||||
Cache = SqliteCacheMode.Shared,
|
||||
Mode = SqliteOpenMode.ReadWriteCreate,
|
||||
DefaultTimeout = 30
|
||||
};
|
||||
var defaultConnection = builder.Configuration.GetConnectionString("DefaultConnection")
|
||||
?? throw new InvalidOperationException("ConnectionStrings:DefaultConnection is required.");
|
||||
|
||||
builder.Services.AddDbContext<LiveRecorderDbContext>(options =>
|
||||
options.UseSqlite(sqliteConnectionStringBuilder.ToString()));
|
||||
options.UseNpgsql(defaultConnection, npgsql =>
|
||||
npgsql.MigrationsAssembly(typeof(LiveRecorderDbContext).Assembly.FullName)));
|
||||
|
||||
builder.Services.AddScoped<IUnitOfWork>(provider => provider.GetRequiredService<LiveRecorderDbContext>());
|
||||
builder.Services.AddScoped<IAppSettingRepository, AppSettingRepository>();
|
||||
@@ -150,6 +146,7 @@ builder.Services.AddScoped<StoppedOrphanRecordSessionCleanupService>();
|
||||
builder.Services.AddScoped<PlatformHttpClientFactory>();
|
||||
builder.Services.AddScoped<RecordUploadService>();
|
||||
builder.Services.AddScoped<DatabaseInitializer>();
|
||||
builder.Services.AddScoped<SqliteToPostgresMigrationService>();
|
||||
|
||||
builder.Services.AddSingleton<BilibiliWbiSigner>();
|
||||
builder.Services.AddScoped<BilibiliHttpClient>();
|
||||
@@ -183,11 +180,25 @@ app.UseMiddleware<ApiTokenAuthenticationMiddleware>();
|
||||
app.MapGet("/", () => Results.Redirect("/swagger"));
|
||||
app.MapControllers();
|
||||
|
||||
if (!resetRecordingData)
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var initializer = scope.ServiceProvider.GetRequiredService<DatabaseInitializer>();
|
||||
await initializer.InitializeAsync(seedDefaults: migrateSqlitePath is null, cancellationToken: default);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(migrateSqlitePath))
|
||||
{
|
||||
using var scope = app.Services.CreateScope();
|
||||
var initializer = scope.ServiceProvider.GetRequiredService<DatabaseInitializer>();
|
||||
await initializer.InitializeAsync();
|
||||
var migrator = scope.ServiceProvider.GetRequiredService<SqliteToPostgresMigrationService>();
|
||||
var report = await migrator.MigrateAsync(migrateSqlitePath);
|
||||
|
||||
Console.WriteLine($"SQLite migration completed. Source={report.SourcePath}");
|
||||
foreach (var tableName in report.SourceCounts.Keys.OrderBy(static item => item, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"{tableName}: {report.SourceCounts[tableName]} -> {report.TargetCounts[tableName]}");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (resetRecordingData)
|
||||
@@ -196,16 +207,15 @@ if (resetRecordingData)
|
||||
var dbContext = scope.ServiceProvider.GetRequiredService<LiveRecorderDbContext>();
|
||||
var before = await ReadRecordingDataCountsAsync(dbContext);
|
||||
|
||||
await using (var transaction = await dbContext.Database.BeginTransactionAsync())
|
||||
{
|
||||
await dbContext.Database.ExecuteSqlRawAsync(
|
||||
"DELETE FROM SystemLogEntries WHERE LiveRoomId IS NOT NULL OR RecordSessionId IS NOT NULL OR RecordTaskId IS NOT NULL;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM RecordResults;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM RecordTasks;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM RecordSessions;");
|
||||
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM LiveRooms;");
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
await using var transaction = await dbContext.Database.BeginTransactionAsync();
|
||||
await dbContext.SystemLogEntries
|
||||
.Where(item => item.LiveRoomId != null || item.RecordSessionId != null || item.RecordTaskId != null)
|
||||
.ExecuteDeleteAsync();
|
||||
await dbContext.RecordResults.ExecuteDeleteAsync();
|
||||
await dbContext.RecordTasks.ExecuteDeleteAsync();
|
||||
await dbContext.RecordSessions.ExecuteDeleteAsync();
|
||||
await dbContext.LiveRooms.ExecuteDeleteAsync();
|
||||
await transaction.CommitAsync();
|
||||
|
||||
var after = await ReadRecordingDataCountsAsync(dbContext);
|
||||
Console.WriteLine("Recording data reset complete.");
|
||||
@@ -249,3 +259,16 @@ static SocketsHttpHandler CreateDouyinHttpHandler(bool useProxy)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static string? GetOptionValue(string[] args, string optionName)
|
||||
{
|
||||
for (var index = 0; index < args.Length - 1; index++)
|
||||
{
|
||||
if (string.Equals(args[index], optionName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return args[index + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user