Commit Graph

18 Commits

Author SHA1 Message Date
cec9cfe2ed Refactor Health UI and enable static file support
- Added `app.UseStaticFiles()` to serve static files from `wwwroot`.
- Changed root path redirection to `/health-ui`.
- Moved inline CSS/JS from `Program.cs` to `health-ui.css` and `health-ui.js`.
- Updated navigation links in the health check HTML.
- Enhanced Health UI with improved styles and animations.
- Introduced countdown auto-refresh in `health-ui.js`.
- Updated `launchSettings.json` to start at the root URL.
2026-07-13 13:08:22 +02:00
eb2514f1fc Add health check UI and Serilog dashboard integration
Introduced a `/health-ui` route with a custom HTML-based health check UI, leveraging `HealthCheckService`. Added `GenerateHealthCheckHtml` to dynamically render health check results with Bootstrap styling, auto-refresh, and detailed status reporting.

Enabled Serilog self-diagnostics and integrated `app.UseSerilogUi()` for a Serilog log dashboard. Enhanced user experience with navigation links, animations, and responsive design. Improved observability and monitoring capabilities.
2026-07-13 13:02:11 +02:00
8a05d86285 feat: Add health check monitoring for ProfileWorker
ProfileWorker changes:
- Implement IHealthCheck interface
- Replace _workCount with DateTime-based tracking
- Track _lastSuccessfulRun, _consecutiveFailures, _lastException
- Graceful shutdown handling (OperationCanceledException)
- Health states: Healthy, Degraded (1-2 failures), Unhealthy (3x interval)

DependencyInjection changes:
- Register ProfileWorker as singleton (for health check access)
- Use factory pattern for IHostedService registration

Program.cs changes:
- Add health check service with ProfileWorker
- Map /health endpoint (full JSON response with all checks)
- Map /health/ready endpoint (filtered by 'ready' tag)
- Custom JSON response writer with detailed metrics
2026-07-13 12:19:11 +02:00
b48e3d1823 config: Add ProfileWorker configuration section
- ProfileWorker:IntervalMS = 1000 (1 second sync interval)
- Configurable via appsettings.json with IOptions pattern
- Validated at startup via ProfileWorkerOptionsValidator
2026-07-13 11:59:59 +02:00
41b08e3454 refactor: Use AddProfileWorker extension method in Program.cs
- Replace direct AddHostedService<ProfileManager> with AddProfileWorker()
- Enables IOptions configuration and validation at startup
- Add using directive for ECMJobRunner.WebCron.ProfileWorker namespace
2026-07-13 11:59:52 +02:00
2fd99694b6 refactor: Remove monolithic ProfileManager
Replaced by modular ProfileWorker namespace with better separation of concerns.
2026-07-13 11:59:44 +02:00
66fad12e63 feat: Add ProfileWork with Hangfire job synchronization
- ProfileWork.cs: Business logic for DB-to-Hangfire sync
- Fetches active profiles from database via MediatR
- Registers/updates Hangfire recurring jobs with local timezone
- Removes stale jobs (deleted from DB)
- O(n) performance optimization using HashSet for lookups
- Uses ProfileWorker's stopping token for graceful shutdown

Job lifecycle:
- ProfileWorker stops → All running jobs cancelled via token closure
- Jobs use RecurringJobOptions with TimeZoneInfo.Local
- Automatic retry support via Hangfire [AutomaticRetry] attribute
2026-07-13 11:59:38 +02:00
f67c321380 refactor: Extract ProfileWorker into modular components
- Create ProfileWorker namespace with 4 separate components
- ProfileWorker.cs: BackgroundService orchestrator with IOptions support
- ProfileWorkerOptions.cs: Configuration model with validation
- ProfileCache.cs: Thread-safe cache using composition pattern
- DependencyInjection.cs: Service registration with IValidateOptions

Benefits:
- Separation of concerns (orchestration, config, state, DI)
- IOptions pattern for appsettings.json configuration
- Startup validation for configuration errors
- Better testability and maintainability
2026-07-13 11:59:23 +02:00
cba1aa85d0 feat: Add root path redirect to Hangfire dashboard
- Map root path (/) to redirect to /hangfire dashboard
- Improves user experience by providing direct access to main dashboard
- Users accessing the application root will be automatically redirected to Hangfire
2026-07-13 09:51:53 +02:00
def4d7b7c7 refactor: Move log directory configuration to Application section
- Move LogDirectory from Logging section to Application section in appsettings.json
- Update Program.cs to read from Application:LogDirectory instead of Logging:LogDirectory
- Fix JSON schema validation warning for non-standard Logging properties
- Application section now holds custom application-specific settings
- Standard Logging and Serilog sections remain clean and schema-compliant
2026-07-13 09:51:01 +02:00
d61d14145a feat: Add Serilog SQLite sink and Serilog.UI dashboard with centralized log directory configuration
- Add Serilog.Sinks.SQLite v7.0.0 for structured logging to SQLite database
- Add Serilog.UI v3.2.0 and Serilog.UI.SqliteProvider v1.1.0 for web-based log viewer
- Add Serilog.Settings.Configuration v10.0.1 for configuration support
- Configure SQLite log storage at E:\LogFiles\Digital Data\ECMJobRunner.WebCron\logs.db
- Add Serilog.UI dashboard at /serilog-ui endpoint
- Centralize log directory configuration in appsettings.json (Logging:LogDirectory)
- Configure Serilog programmatically with Console and SQLite sinks
- Remove deprecated Serilog configuration from appsettings files (now using code-based config)
- Enable Serilog self-diagnostics for troubleshooting
- Both Serilog sink and Serilog.UI use same SQLite database path from configuration
2026-07-12 17:33:19 +02:00
8b0f97c330 feat: Add Hangfire cronjob system with web dashboard, Windows Service support, and Serilog file/console logging
- Add Hangfire packages (AspNetCore, Core, InMemory, SqlServer) with configurable storage (InMemory vs SQL Server)
- Configure Hangfire dashboard at /hangfire with AllowAllDashboardAuthorizationFilter (no auth for development)
- Add Microsoft.Extensions.Hosting.WindowsServices package with conditional UseWindowsService() based on HostingOptions:UseWindowsService config
- Create ProfileManager BackgroundService with IServiceScopeFactory for scoped service resolution per iteration
- Create AllowAllDashboardAuthorizationFilter for Hangfire dashboard access
- Create DtoExtensions with JobId() and ToJob() helper methods
- Configure Serilog with file sink (Production: Logs/log-.txt, daily rolling, 30 day retention) and console sink (Development)
- Add Serilog enrichers: FromLogContext, WithMachineName, WithThreadId
- Update appsettings.json with Hangfire:InMemory flag, HostingOptions:UseWindowsService flag, and Serilog configuration
- Create appsettings.Development.json with console-specific Serilog configuration
2026-07-12 04:49:22 +02:00
d50232b0bb feat: Add Windows Service hosting support
- Add Microsoft.Extensions.Hosting.WindowsServices package
- Add HostingOptions:UseWindowsService configuration flag to appsettings.json
- Configure Program.cs to optionally run as Windows Service based on config
- IIS hosting continues to work by default (UseWindowsService=false)
- Delete obsolete Worker.cs that was conflicting with ProfileManager
2026-07-12 00:23:59 +02:00
59bef13f5d fix: Resolve scoped service dependency issue in ProfileManager
- Replace IMediator constructor injection with IServiceScopeFactory
- Create new scope in ExecuteAsync loop to resolve scoped services (ISQLExecutor)
- Fixes: Cannot resolve scoped service from root provider error
- Enables ProfileManager to properly execute MediatR queries with scoped dependencies
2026-07-12 00:22:33 +02:00
7efc77ca51 feat: Add AllowAllDashboardAuthorizationFilter for development
- Create authorization filter to bypass Hangfire dashboard authentication
- Allow unrestricted access to /hangfire dashboard for local development
- Note: Should be replaced with proper authentication in production
2026-07-12 00:04:25 +02:00
ad2ab741ff feat: Add ProfileManager for automatic Hangfire job scheduling
- Create ProfileManager background service that polls database every 1 second
- Query active profiles with cron schedules via MediatR GetProfileQuery
- Auto-create/update Hangfire recurring jobs using IRecurringJobManager
- Jobs execute TriggeringDEXJobBatchCommand via IMediator dependency injection
- Add profile caching with schedule change detection to avoid redundant updates
- Create DtoExtensions with JobId() and ToJob() helper methods for profile-to-command conversion
2026-07-12 00:04:13 +02:00
eb7adc741a feat: Add Hangfire infrastructure with dynamic storage configuration
- Install Hangfire packages (Core, AspNetCore, SqlServer, InMemory)
- Configure Hangfire in Program.cs with boolean InMemory flag from appsettings
- Add Hangfire dashboard at /hangfire route
- Update appsettings.json with Hangfire:InMemory configuration
- Update launchSettings.json with new launch URL
- Remove obsolete Worker.cs background service
2026-07-12 00:04:00 +02:00
4767bcfbe1 Add .NET 8.0 web app with minimal API and background worker
Introduced a new .NET 8.0 web application project with a minimal API setup.
Configured Swagger for API documentation and added a `Worker` class as a
background service for periodic tasks.

Added `launchSettings.json` to define development profiles for HTTP, HTTPS,
and IIS Express. Configured logging levels in `appsettings.json` and
`appsettings.Development.json`.

Included `Swashbuckle.AspNetCore` package for Swagger integration and
configured the HTTP request pipeline to support development and production
environments.
2026-07-11 12:56:58 +02:00