using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using Prometheus; using VoidCat.Model; using VoidCat.Services; using VoidCat.Services.Analytics; using VoidCat.Services.Migrations; namespace VoidCat; static class Program { [Flags] enum RunModes { Webserver = 1, BackgroundJobs = 2, Migrations = 4, All = 255 } public static async Task Main(string[] args) { JsonConvert.DefaultSettings = () => VoidStartup.ConfigJsonSettings(new()); RunModes mode = args.Length == 0 ? RunModes.All : 0; if (args.Contains("--run-webserver")) { mode |= RunModes.Webserver; } if (args.Contains("--run-migrations")) { mode |= RunModes.Migrations; } if (args.Contains("--run-background-jobs")) { mode |= RunModes.BackgroundJobs; } Console.WriteLine($"Running with modes: {mode}"); async Task RunMigrations(IServiceProvider services) { using var migrationScope = services.CreateScope(); var migrations = migrationScope.ServiceProvider.GetServices(); var logger = migrationScope.ServiceProvider.GetRequiredService>(); foreach (var migration in migrations.OrderBy(a => a.Order)) { logger.LogInformation("Running migration: {Migration}", migration.GetType().Name); var res = await migration.Migrate(args); logger.LogInformation("== Result: {Result}", res.ToString()); if (res == IMigration.MigrationResult.ExitCompleted) { return; } } } if (mode.HasFlag(RunModes.Webserver)) { var builder = WebApplication.CreateBuilder(args); var services = builder.Services; var configuration = builder.Configuration; var voidSettings = configuration.GetSection("Settings").Get(); services.AddSingleton(voidSettings); services.AddSingleton(voidSettings.Strike ?? new()); var seqSettings = configuration.GetSection("Seq"); builder.Logging.AddSeq(seqSettings); ConfigureDb(services, voidSettings); services.AddBaseServices(voidSettings); services.AddDatabaseServices(voidSettings); services.AddWebServices(voidSettings); if (mode.HasFlag(RunModes.Migrations)) { services.AddMigrations(voidSettings); } if (mode.HasFlag(RunModes.BackgroundJobs)) { services.AddBackgroundServices(voidSettings); } var app = builder.Build(); if (mode.HasFlag(RunModes.Migrations)) { await RunMigrations(app.Services); } app.UseStaticFiles(); app.UseHttpLogging(); app.UseRouting(); app.UseHttpMetrics(); app.UseCors(); app.UseSwagger(); app.UseSwaggerUI(); app.UseAuthentication(); app.UseAuthorization(); app.UseHealthChecks("/healthz"); app.UseMiddleware(); app.UseEndpoints(ep => { ep.MapControllers(); ep.MapMetrics(); ep.MapRazorPages(); ep.MapFallbackToFile("index.html"); }); await app.RunAsync(); } else { // daemon style, dont run web server var builder = Host.CreateDefaultBuilder(args); builder.ConfigureServices((context, services) => { var voidSettings = context.Configuration.GetSection("Settings").Get(); services.AddSingleton(voidSettings); services.AddSingleton(voidSettings.Strike ?? new()); ConfigureDb(services, voidSettings); services.AddBaseServices(voidSettings); services.AddDatabaseServices(voidSettings); if (mode.HasFlag(RunModes.Migrations)) { services.AddMigrations(voidSettings); } if (mode.HasFlag(RunModes.BackgroundJobs)) { services.AddBackgroundServices(voidSettings); } }); builder.ConfigureLogging((context, logging) => { logging.AddSeq(context.Configuration.GetSection("Seq")); }); var app = builder.Build(); if (mode.HasFlag(RunModes.Migrations)) { await RunMigrations(app.Services); } if (mode.HasFlag(RunModes.BackgroundJobs)) { await app.RunAsync(); } } } private static void ConfigureDb(IServiceCollection services, VoidSettings settings) { if (settings.HasPostgres()) { services.AddDbContext(o => o.UseNpgsql(settings.Postgres!)); } } /// /// Dummy method for EF core migrations /// /// /// // ReSharper disable once UnusedMember.Global public static IHostBuilder CreateHostBuilder(string[] args) { var dummyHost = Host.CreateDefaultBuilder(args); dummyHost.ConfigureServices((ctx, svc) => { var settings = ctx.Configuration.GetSection("Settings").Get(); ConfigureDb(svc, settings); }); return dummyHost; } }