refactor: Rename TrueCV to RealCV throughout codebase

- Renamed all directories (TrueCV.* -> RealCV.*)
- Renamed all project files (.csproj)
- Renamed solution file (TrueCV.sln -> RealCV.sln)
- Updated all namespaces in C# and Razor files
- Updated project references
- Updated CSS variable names

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-22 20:47:55 +00:00
parent 6f384f8d09
commit 92a3b60878
107 changed files with 693 additions and 554 deletions

View File

@@ -0,0 +1,132 @@
using Hangfire;
using Hangfire.SqlServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Extensions.Http;
using RealCV.Application.Interfaces;
using RealCV.Infrastructure.Configuration;
using RealCV.Infrastructure.Data;
using RealCV.Infrastructure.ExternalApis;
using RealCV.Infrastructure.Jobs;
using RealCV.Infrastructure.Services;
namespace RealCV.Infrastructure;
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
// Configure DbContext with SQL Server
// AddDbContextFactory enables thread-safe parallel operations
services.AddDbContextFactory<ApplicationDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection"),
sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
}));
// Also register DbContext for scoped injection (non-parallel scenarios)
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection"),
sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
}));
// Configure Hangfire with SQL Server storage
services.AddHangfire(config => config
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(
configuration.GetConnectionString("HangfireConnection"),
new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
}));
services.AddHangfireServer();
// Configure options
services.Configure<CompaniesHouseSettings>(
configuration.GetSection(CompaniesHouseSettings.SectionName));
services.Configure<AnthropicSettings>(
configuration.GetSection(AnthropicSettings.SectionName));
services.Configure<AzureBlobSettings>(
configuration.GetSection(AzureBlobSettings.SectionName));
services.Configure<LocalStorageSettings>(
configuration.GetSection(LocalStorageSettings.SectionName));
// Configure HttpClient for CompaniesHouseClient with retry policy
services.AddHttpClient<CompaniesHouseClient>((serviceProvider, client) =>
{
var settings = configuration
.GetSection(CompaniesHouseSettings.SectionName)
.Get<CompaniesHouseSettings>();
if (settings is not null)
{
client.BaseAddress = new Uri(settings.BaseUrl);
}
})
.AddPolicyHandler(GetRetryPolicy());
// Register services
services.AddScoped<ICVParserService, CVParserService>();
services.AddScoped<ICompanyNameMatcherService, AICompanyNameMatcherService>();
services.AddScoped<ICompanyVerifierService, CompanyVerifierService>();
services.AddScoped<IEducationVerifierService, EducationVerifierService>();
services.AddScoped<ITimelineAnalyserService, TimelineAnalyserService>();
services.AddScoped<ICVCheckService, CVCheckService>();
services.AddScoped<IUserContextService, UserContextService>();
services.AddScoped<IAuditService, AuditService>();
// Register file storage - use local storage if configured, otherwise Azure
var useLocalStorage = configuration.GetValue<bool>("UseLocalStorage");
if (useLocalStorage)
{
services.AddScoped<IFileStorageService, LocalFileStorageService>();
}
else
{
services.AddScoped<IFileStorageService, FileStorageService>();
}
// Register Hangfire jobs
services.AddTransient<ProcessCVCheckJob>();
return services;
}
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (outcome, timespan, retryAttempt, context) =>
{
// Logging could be added here via ILogger if injected
});
}
}