using ECMJobRunner.Application; using ECMJobRunner.Infrastructure; using ECMJobRunner.WebCron; using Hangfire; using Hangfire.SqlServer; using Microsoft.Data.SqlClient; using Serilog; // Configure Serilog from appsettings.json Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true) .Build()) .CreateLogger(); try { Log.Information("Starting ECMJobRunner.WebCron application"); var builder = WebApplication.CreateBuilder(args); // Use Serilog for logging builder.Host.UseSerilog(); // Configure Windows Service hosting if enabled if (builder.Configuration.GetValue("HostingOptions:UseWindowsService")) { builder.Host.UseWindowsService(); } // Add services to the container. builder.Services.AddControllers(); builder.Services.AddHostedService(); // Register services var cnnStr = builder.Configuration.GetConnectionString("SDD-VMP04-SQL17") ?? throw new InvalidOperationException("Connection string 'SDD-VMP04-SQL17' not found."); builder.Services.AddJobRunnerInfrastructure(cnnStr); var recClientApiUrl = builder.Configuration.GetValue("ReC:ApiUrl") ?? throw new InvalidOperationException("ReC:ApiUrl not found."); builder.Services.AddJobRunnerServices(recClientApiUrl); // Get Hangfire storage configuration var useInMemory = builder.Configuration.GetValue("Hangfire:InMemory"); // Add Hangfire services with configurable storage builder.Services.AddHangfire(configuration => { configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_180) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings(); // Configure storage based on appsettings if (useInMemory) { configuration.UseInMemoryStorage(); } else // Use SQL Server storage { configuration.UseSqlServerStorage(cnnStr, new SqlServerStorageOptions { CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), QueuePollInterval = TimeSpan.Zero, UseRecommendedIsolationLevel = true, DisableGlobalLocks = true, SqlClientFactory = SqlClientFactory.Instance }); } }); // Add Hangfire server builder.Services.AddHangfireServer(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); // Add Hangfire Dashboard with no authentication (for development) app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new[] { new AllowAllDashboardAuthorizationFilter() } }); app.MapControllers(); app.Run(); } catch (Exception ex) { Log.Fatal(ex, "Application terminated unexpectedly"); } finally { Log.CloseAndFlush(); }