140 lines
4.4 KiB
C#
140 lines
4.4 KiB
C#
using JSMR.Application.DI;
|
|
using JSMR.Infrastructure.Data;
|
|
using JSMR.Infrastructure.DI;
|
|
using JSMR.Worker.Options;
|
|
using JSMR.Worker.Services;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using System.CommandLine;
|
|
|
|
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
|
|
|
// Build a single configuration pipeline
|
|
builder.Configuration
|
|
.SetBasePath(builder.Environment.ContentRootPath)
|
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
|
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true)
|
|
// Add user secrets (works regardless of environment when optional: true)
|
|
.AddUserSecrets(typeof(Program).Assembly, optional: true)
|
|
.AddEnvironmentVariables();
|
|
|
|
// Pull the connection string from config (appsettings or secrets or env)
|
|
string connectionString = builder.Configuration.GetConnectionString("AppDb")
|
|
?? throw new InvalidOperationException("Missing ConnectionStrings:AppDb");
|
|
|
|
//builder.Services.AddSerilog(o => o
|
|
// .WriteTo.Console()
|
|
// .MinimumLevel.Information());
|
|
|
|
builder.Services
|
|
.AddApplication()
|
|
.AddInfrastructure()
|
|
.AddMemoryCache();
|
|
|
|
//string connectionString = builder.Configuration.GetConnectionString("AppDb")
|
|
// ?? throw new InvalidOperationException("Missing ConnectionStrings:AppDb");
|
|
|
|
builder.Services.AddDbContextFactory<AppDbContext>(optionsBuilder =>
|
|
optionsBuilder
|
|
.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))
|
|
.EnableSensitiveDataLogging(false));
|
|
|
|
// Worker services
|
|
builder.Services.AddSingleton<ICheckpointStore, FileCheckpointStore>();
|
|
builder.Services.AddTransient<PagedScanRunner>();
|
|
|
|
RootCommand rootCommand = new("JSMR worker");
|
|
Command scan = new("scan", "Scan and update the database");
|
|
|
|
Option<string?> localeOption = new("--locale", "-l")
|
|
{
|
|
Description = "Locale (Japanese/English)",
|
|
Required = false
|
|
};
|
|
|
|
Option<int?> startOption = new("--start", "-s")
|
|
{
|
|
Description = "Start page (default = checkpoint+1 or 1)"
|
|
};
|
|
|
|
Option<int?> endOption = new("--end", "-e")
|
|
{
|
|
Description = "End page (optional)"
|
|
};
|
|
|
|
Option<int?> sizeOption = new("--pageSize", "-ps")
|
|
{
|
|
Description = "Page size (default from config or 100)",
|
|
DefaultValueFactory = _ => 100
|
|
};
|
|
|
|
Option<bool> watchOption = new("--watch", "-w")
|
|
{
|
|
Description = "Loop forever",
|
|
DefaultValueFactory = _ => false
|
|
};
|
|
|
|
Option<TimeSpan> everyOption = new("--every", "-e")
|
|
{
|
|
Description = "Interval when --watch is set",
|
|
DefaultValueFactory = _ => TimeSpan.FromMinutes(5)
|
|
};
|
|
|
|
|
|
scan.Add(localeOption);
|
|
scan.Add(startOption);
|
|
scan.Add(endOption);
|
|
scan.Add(sizeOption);
|
|
scan.Add(watchOption);
|
|
scan.Add(everyOption);
|
|
|
|
scan.SetAction(async (parseResult, cancellationToken) =>
|
|
{
|
|
using var host = builder.Build();
|
|
var runner = host.Services.GetRequiredService<PagedScanRunner>();
|
|
|
|
ScanOptions options = new()
|
|
{
|
|
Locale = parseResult.GetValue(localeOption) ?? default!,
|
|
StartPage = parseResult.GetValue(startOption),
|
|
EndPage = parseResult.GetValue(endOption),
|
|
PageSize = parseResult.GetValue(sizeOption),
|
|
Watch = parseResult.GetValue(watchOption),
|
|
Interval = parseResult.GetValue(everyOption)
|
|
};
|
|
|
|
using CancellationTokenSource cancellationTokenSource = new();
|
|
|
|
Console.CancelKeyPress += (_, eventArgs) =>
|
|
{
|
|
eventArgs.Cancel = true;
|
|
cancellationTokenSource.Cancel();
|
|
};
|
|
|
|
await runner.RunAsync(options, cancellationTokenSource.Token);
|
|
});
|
|
|
|
rootCommand.Add(scan);
|
|
|
|
//rootCommand.SetAction(async (parseResult, cancellationToken) => await rootCommand.InvokeAsync("scan"));
|
|
|
|
Command schemaDumpCommand = new("schema-dump", "Emit EF model as a full create script (desired.sql)");
|
|
|
|
schemaDumpCommand.SetAction(async (parseResult, cancellationToken) =>
|
|
{
|
|
using var host = builder.Build();
|
|
await using var scope = host.Services.CreateAsyncScope();
|
|
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
|
|
var sql = db.Database.GenerateCreateScript();
|
|
var outPath = Path.GetFullPath("desired.sql");
|
|
await File.WriteAllTextAsync(outPath, sql, cancellationToken);
|
|
|
|
Console.WriteLine($"[OK] Wrote EF model create script to: {outPath}");
|
|
});
|
|
|
|
rootCommand.Add(schemaDumpCommand);
|
|
|
|
return await rootCommand.Parse(args).InvokeAsync(); |