Add XML doc to all service interfaces and implementations (#26)
- Update CLAUDE.md: replace incorrect 'no XML doc on internal code' rule with the correct convention (XML doc on all public methods and non-trivial private/protected helpers) - Restore /// <summary> on FileDownloadController private helpers (HandleRangeRequest, StreamRangeAsync) - Add full XML doc to all service contracts: ICaptchaVerifier, IEmailSender, ICvMatcherService, IJobTextExtractor, IJobTokenService, IDocumentClassifier, IRagService, ITextChunker, ITextExtractor, IEmailTemplateService, ITemplateService - Add /// <summary> and /// <inheritdoc /> to all concrete service classes and their methods: RecaptchaVerifier, EmailApiEmailSender, SmtpEmailDispatcher, CvMatcherService, JobTextExtractor, JobTokenService, RagService, DocumentClassifier, TextChunker, TextExtractor, HtmlJobSearcher, CvSearchEmailSender, CvSearchJobTask, EmailTemplateService, DbTemplateService Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,10 @@ using Microsoft.Extensions.Options;
|
||||
|
||||
namespace CvSearchJob.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// Background job task that processes pending job search sessions: scrapes providers,
|
||||
/// scores each URL against the CV via the matcher API, persists results, and sends the results email.
|
||||
/// </summary>
|
||||
public sealed class CvSearchJobTask : IJobTask
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
@@ -41,6 +45,11 @@ public sealed class CvSearchJobTask : IJobTask
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the scheduler on each tick. Resets orphaned sessions, picks the oldest pending session,
|
||||
/// runs the full search pipeline, and sends the results email.
|
||||
/// Does nothing when <c>JobSearch:Enabled</c> is <c>false</c>.
|
||||
/// </summary>
|
||||
public async Task ExecuteAsync(IConfiguration parametersSection, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_settings.Enabled) return;
|
||||
@@ -92,6 +101,10 @@ public sealed class CvSearchJobTask : IJobTask
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs the full search pipeline for a session: scrapes all providers, deduplicates URLs,
|
||||
/// scores each candidate via the matcher API, and persists results that meet the minimum score threshold.
|
||||
/// </summary>
|
||||
private async Task<List<JobSearchResultEntity>> RunSearchAsync(
|
||||
JobSearchSessionEntity session,
|
||||
CvSearchDbContext db,
|
||||
@@ -163,6 +176,10 @@ public sealed class CvSearchJobTask : IJobTask
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialises the provider configuration snapshot stored on the session.
|
||||
/// Falls back to the current live config when the snapshot is absent or unparseable.
|
||||
/// </summary>
|
||||
private List<JobProviderConfig> GetProviders(string? providerConfigJson)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(providerConfigJson)) return _settings.Providers.Where(p => p.Enabled).ToList();
|
||||
@@ -178,6 +195,10 @@ public sealed class CvSearchJobTask : IJobTask
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Infers the provider name from the job URL by matching against each provider's <c>JobLinkContains</c> pattern.
|
||||
/// Falls back to the URL hostname when no provider matches.
|
||||
/// </summary>
|
||||
private static string GuessProvider(string url, List<JobProviderConfig> providers)
|
||||
{
|
||||
foreach (var p in providers)
|
||||
@@ -190,6 +211,9 @@ public sealed class CvSearchJobTask : IJobTask
|
||||
return Uri.TryCreate(url, UriKind.Absolute, out var uri) ? uri.Host : "unknown";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the CV PDF filename from the document ID.
|
||||
/// </summary>
|
||||
private static string BuildCvFileName(string cvDocumentId)
|
||||
{
|
||||
// Strip non-alphanumeric characters so the filename is safe for all OS/email clients.
|
||||
|
||||
Reference in New Issue
Block a user