90 lines
3.3 KiB
C#
90 lines
3.3 KiB
C#
using System.Text.Json;
|
|
using JobTrackerApi.Data;
|
|
using JobTrackerApi.Services.JobImport;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace JobTrackerApi.Services;
|
|
|
|
public sealed class JobEnrichmentHostedService : BackgroundService
|
|
{
|
|
private readonly IServiceProvider _services;
|
|
private readonly ILogger<JobEnrichmentHostedService> _logger;
|
|
|
|
public JobEnrichmentHostedService(IServiceProvider services, ILogger<JobEnrichmentHostedService> logger)
|
|
{
|
|
_services = services;
|
|
_logger = logger;
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
|
|
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var db = scope.ServiceProvider.GetRequiredService<JobTrackerContext>();
|
|
var summarizer = scope.ServiceProvider.GetRequiredService<ISummarizerService>();
|
|
|
|
var jobs = await db.JobApplications
|
|
.Where(j => !j.IsDeleted)
|
|
.Where(j => string.IsNullOrWhiteSpace(j.ShortSummary) || string.IsNullOrWhiteSpace(j.Tags))
|
|
.OrderByDescending(j => j.DateApplied)
|
|
.Take(20)
|
|
.ToListAsync(stoppingToken);
|
|
|
|
var changed = 0;
|
|
foreach (var job in jobs)
|
|
{
|
|
var sourceText = string.IsNullOrWhiteSpace(job.Description) ? job.Notes : job.Description;
|
|
|
|
if (string.IsNullOrWhiteSpace(job.Tags) && !string.IsNullOrWhiteSpace(sourceText))
|
|
{
|
|
var tags = SkillTagger.Detect(sourceText)
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
|
|
if (tags.Count > 0)
|
|
{
|
|
job.Tags = JsonSerializer.Serialize(tags);
|
|
changed++;
|
|
}
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(job.ShortSummary) && !string.IsNullOrWhiteSpace(sourceText))
|
|
{
|
|
try
|
|
{
|
|
var shortSummary = await summarizer.SummarizeAsync(sourceText, 80, 20);
|
|
if (!string.IsNullOrWhiteSpace(shortSummary))
|
|
{
|
|
job.ShortSummary = shortSummary;
|
|
changed++;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Best effort; leave for a later pass.
|
|
}
|
|
}
|
|
}
|
|
|
|
if (changed > 0)
|
|
{
|
|
await db.SaveChangesAsync(stoppingToken);
|
|
_logger.LogInformation("Backfilled tags/summaries for {Count} job fields.", changed);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Job enrichment background pass failed.");
|
|
}
|
|
|
|
await Task.Delay(TimeSpan.FromMinutes(10), stoppingToken);
|
|
}
|
|
}
|
|
}
|