- 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
40 lines
1.3 KiB
C#
40 lines
1.3 KiB
C#
using Microsoft.Extensions.Options;
|
|
|
|
namespace ECMJobRunner.WebCron.ProfileWorker;
|
|
|
|
public class ProfileWorker(
|
|
ILogger<ProfileWorker> Logger,
|
|
IServiceScopeFactory ScopeFactory,
|
|
IOptions<ProfileWorkerOptions> Options) : BackgroundService
|
|
{
|
|
private readonly ProfileWorkerOptions _options = Options.Value;
|
|
|
|
private int _workCount = 0;
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
_workCount++;
|
|
if (Logger.IsEnabled(LogLevel.Information))
|
|
{
|
|
Logger.LogInformation("Worker running {workCount} at: {time}", _workCount, DateTimeOffset.Now);
|
|
}
|
|
|
|
try
|
|
{
|
|
// Create a scope to resolve scoped services (ISQLExecutor used by MediatR pipeline)
|
|
using var scope = ScopeFactory.CreateScope();
|
|
var work = scope.ServiceProvider.GetRequiredService<ProfileWork>();
|
|
await work.ExecuteAsync(stoppingToken);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.LogError(ex, "An unexpected error occurred in ProfileWorker. Work count: {workCount}", _workCount);
|
|
}
|
|
|
|
await Task.Delay(_options.IntervalMS, stoppingToken);
|
|
}
|
|
}
|
|
}
|