⚙️ Phase 7: Hangfire Background Job Scheduling
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 4s
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 4s
Hangfire Integration for Automated Tasks ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ✅ SchedulerService.cs (New) - Background job scheduling with Hangfire - 4 Recurring Jobs: * Daily collection (9:00 AM) * Hourly price update (9 AM-3 PM, Mon-Fri) * Weekly report (Friday 5:00 PM) * Monthly optimization (1st day, 2:00 AM) - Methods: * InitializeSchedules() - Setup recurring jobs * RunDailyCollectionAsync() - Daily data collection * UpdatePricesAsync() - Hourly price refresh * FetchPriceAsync(ticker) - Single ticker price fetch * GenerateWeeklyReportAsync() - Weekly report generation * RunMonthlyOptimizationAsync() - Monthly optimization * EnqueueJob() - One-time job enqueue * GetJobStatus() - Check job status * CancelScheduledJob() - Cancel scheduled job - HangfireServiceExtensions: * AddHangfireServices() - Register Hangfire with SQL Server * UseHangfireSetup() - Initialize schedules and dashboard * HangfireAuthorizationFilter - Basic auth for dashboard ✅ Program.cs (Updated) - Added Hangfire imports - Registered Hangfire services with SQL Server storage - Added Hangfire middleware setup - Dashboard available at /hangfire - Graceful error handling for Hangfire failures Features: ✓ Recurring job scheduling with Cron expressions ✓ Queue-based job processing ✓ SQL Server job storage (persistent) ✓ Worker thread pool (CPU-count * 2) ✓ Job retry and error handling ✓ Hangfire Dashboard for monitoring ✓ Logging integration with Serilog ✓ RBAC-ready dashboard authorization Scheduled Tasks: 1. Daily Collection (9:00 AM) - Fetches data for 6 tickers - Logs each ticker collection - Scheduled for market hours 2. Hourly Price Update (9 AM-3 PM, Mon-Fri) - Updates top 3 tickers - Queues individual price jobs - Market-hours only 3. Weekly Report (Friday 5:00 PM) - Generates comprehensive weekly report - Scheduled for end of week 4. Monthly Optimization (1st day, 2:00 AM) - Portfolio optimization - Low-traffic time window Usage Example: Configuration (appsettings.json): Dashboard Access: - URL: http://localhost:5265/hangfire - Features: * Job queue monitoring * Recurring job management * Job history and logs * Failed job handling * Statistics and charts Next: Phase 6 (Testing) & Phase 8 (Deployment) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,9 @@ using Microsoft.AspNetCore.Authentication;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MudBlazor.Services;
|
||||
using QuantEngine.Web.Services;
|
||||
using Hangfire;
|
||||
using Hangfire.SqlServer;
|
||||
|
||||
// Serilog Configuration with Telegram Sink
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
@@ -47,6 +50,17 @@ builder.Services.AddAuthorizationCore();
|
||||
|
||||
builder.Services.AddMudServices();
|
||||
|
||||
// Hangfire Background Job Scheduling
|
||||
try
|
||||
{
|
||||
var hangfireConnectionString = builder.Configuration.GetConnectionString("HangfireConnection") ?? connectionString;
|
||||
builder.Services.AddHangfireServices(hangfireConnectionString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning("Hangfire initialization failed: {Message}", ex.Message);
|
||||
}
|
||||
|
||||
// PostgreSQL Dapper Setup
|
||||
var configuredConnectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||
var fallbackConnectionString = "Host=127.0.0.1;Database=quantenginedb;Username=quantengine_app;Password=CHANGE_ME;Search Path=quantengine;";
|
||||
@@ -143,6 +157,16 @@ app.UseAntiforgery();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
// Initialize Hangfire (dashboard and schedules)
|
||||
try
|
||||
{
|
||||
app.UseHangfireSetup(app.Services);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning("Hangfire setup failed: {Message}", ex.Message);
|
||||
}
|
||||
|
||||
app.MapStaticAssets();
|
||||
|
||||
app.MapGet("/", () => Results.Redirect("/login"));
|
||||
|
||||
Reference in New Issue
Block a user