Files
jobtrackingapp/JobTrackerApi/Services/RulesHostedService.cs
T

61 lines
2.4 KiB
C#

using JobTrackerApi.Data;
using Microsoft.EntityFrameworkCore;
namespace JobTrackerApi.Services;
// Applies deterministic auto-ghost transitions only when explicitly enabled.
public sealed class RulesHostedService(
BackgroundTenantRunner tenants,
IConfiguration configuration,
ILogger<RulesHostedService> logger,
IStartupReadiness startupReadiness) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await startupReadiness.WaitUntilReadyAsync(stoppingToken);
if (!configuration.GetValue("Workers:RulesEnabled", false))
{
logger.LogInformation("Rules worker disabled (Workers:RulesEnabled=false).");
return;
}
await Task.Delay(TimeSpan.FromSeconds(2), stoppingToken);
while (!stoppingToken.IsCancellationRequested)
{
await RunOnceAsync(stoppingToken);
await Task.Delay(TimeSpan.FromMinutes(30), stoppingToken);
}
}
public Task<BackgroundWorkerRunResult> RunOnceAsync(CancellationToken cancellationToken)
{
if (!configuration.GetValue("Workers:RulesEnabled", false))
return Task.FromResult(BackgroundWorkerRunResult.Disabled);
return tenants.RunForJobOwnersAsync("rules", ProcessOwnerAsync, cancellationToken);
}
private static async Task ProcessOwnerAsync(IServiceProvider services, CancellationToken cancellationToken)
{
var db = services.GetRequiredService<JobTrackerContext>();
var settings = await RulesEngine.GetSettings(db, cancellationToken);
var now = DateTime.Now;
var lastMessages = await db.Correspondences
.GroupBy(message => message.JobApplicationId)
.Select(group => new { JobApplicationId = group.Key, Last = group.Max(x => x.Date) })
.ToDictionaryAsync(x => x.JobApplicationId, x => (DateTime?)x.Last, cancellationToken);
var jobs = await db.JobApplications
.Where(job => !job.IsDeleted && job.Status != "Ghosted")
.ToListAsync(cancellationToken);
foreach (var job in jobs)
{
lastMessages.TryGetValue(job.Id, out var lastMessage);
if (RulesEngine.Evaluate(settings, job, now, lastMessage).ShouldGhost)
job.Status = "Ghosted";
}
await db.SaveChangesAsync(cancellationToken);
}
}