61 lines
2.4 KiB
C#
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);
|
|
}
|
|
}
|