using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Polly; using Polly.Extensions.Http; using Serilog; using SaasMediaWorker.Configuration; using SaasMediaWorker.Services; Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}") .CreateLogger(); try { Log.Information("🚀 ContentGen AI Media Worker başlatılıyor..."); var builder = Host.CreateApplicationBuilder(args); builder.Services.AddSerilog(); // Configuration binding builder.Services.Configure( builder.Configuration.GetSection("WorkerSettings")); builder.Services.Configure( builder.Configuration.GetSection("Redis")); builder.Services.Configure( builder.Configuration.GetSection("S3")); builder.Services.Configure( builder.Configuration.GetSection("ApiSettings")); builder.Services.Configure( builder.Configuration.GetSection("FFmpeg")); // Polly Retry Policy — Exponential Backoff + Circuit Breaker var retryPolicy = HttpPolicyExtensions .HandleTransientHttpError() .WaitAndRetryAsync( retryCount: 3, sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)) + TimeSpan.FromMilliseconds(Random.Shared.Next(0, 1000)), onRetry: (outcome, delay, attempt, _) => { Log.Warning( "HTTP Retry #{Attempt} — {Delay}s sonra tekrar denenecek. Hata: {Error}", attempt, delay.TotalSeconds, outcome.Exception?.Message ?? outcome.Result?.StatusCode.ToString()); }); var circuitBreakerPolicy = HttpPolicyExtensions .HandleTransientHttpError() .CircuitBreakerAsync( handledEventsAllowedBeforeBreaking: 5, durationOfBreak: TimeSpan.FromSeconds(30), onBreak: (_, duration) => Log.Error("⚡ Circuit Breaker AÇILDI — {Duration}s bekleniyor", duration.TotalSeconds), onReset: () => Log.Information("✅ Circuit Breaker kapandı — istekler devam ediyor")); var combinedPolicy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy); // HttpClient registrations with Polly builder.Services.AddHttpClient("HiggsField") .AddPolicyHandler(combinedPolicy); builder.Services.AddHttpClient("TTS") .AddPolicyHandler(combinedPolicy); builder.Services.AddHttpClient("Suno") .AddPolicyHandler(combinedPolicy); builder.Services.AddHttpClient("CoreAPI") .AddPolicyHandler(retryPolicy); // Service registrations builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); // Background Service — Redis Queue Consumer builder.Services.AddHostedService(); var host = builder.Build(); await host.RunAsync(); } catch (Exception ex) { Log.Fatal(ex, "💀 Media Worker başlatılamadı!"); } finally { await Log.CloseAndFlushAsync(); }