From 38043cbda3137d50c12c34833abfd2ff9ac061c2 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Mon, 11 May 2026 18:07:51 +0000 Subject: [PATCH] refactor: update infrastructure DI to register split EPUB services and clean up obsolete identity logic --- .../DependencyInjection.cs | 115 +++++++----------- 1 file changed, 46 insertions(+), 69 deletions(-) diff --git a/src/NexusReader.Infrastructure/DependencyInjection.cs b/src/NexusReader.Infrastructure/DependencyInjection.cs index 2b03646..2709c48 100644 --- a/src/NexusReader.Infrastructure/DependencyInjection.cs +++ b/src/NexusReader.Infrastructure/DependencyInjection.cs @@ -1,21 +1,16 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Configuration; -using Pgvector.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.AI; -using GeminiDotnet; -using GeminiDotnet.Extensions.AI; -using NexusReader.Data.Persistence; - +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using NexusReader.Application.Abstractions.Services; +using NexusReader.Data.Persistence; using NexusReader.Infrastructure.Services; -using NexusReader.Infrastructure.Configuration; -using Polly; -using Polly.Retry; -using NexusReader.Domain.Entities; using Microsoft.AspNetCore.Identity; +using NexusReader.Domain.Entities; +using NexusReader.Infrastructure.Identity; using Microsoft.AspNetCore.Authorization; -using NexusReader.Application.Security.Authorization; +using NexusReader.Application.Commands.Sync; +using NexusReader.Infrastructure.Handlers; +using MediatR; namespace NexusReader.Infrastructure; @@ -23,72 +18,54 @@ public static class DependencyInjection { public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) { - var pgConnectionString = configuration.GetConnectionString("PostgresConnection"); - if (!string.IsNullOrEmpty(pgConnectionString)) - { - services.AddDbContextFactory(options => - options.UseNpgsql(pgConnectionString, x => x.UseVector())); - } - else - { - var sqliteConnectionString = configuration.GetConnectionString("SqliteConnection") ?? "Data Source=nexus.db"; - services.AddDbContextFactory(options => - options.UseSqlite(sqliteConnectionString)); - } + var connectionString = configuration.GetConnectionString("DefaultConnection") + ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); - services.Configure(configuration.GetSection(AiSettings.SectionName)); - services.Configure(configuration.GetSection(StripeSettings.SectionName)); - var aiSettings = configuration.GetSection(AiSettings.SectionName).Get() ?? new AiSettings(); - - Console.WriteLine($"[Infrastructure] AI Configured: Model={aiSettings.Model}, KeyPresent={!string.IsNullOrWhiteSpace(aiSettings.ApiKey) && aiSettings.ApiKey != "PLACEHOLDER"}"); - - if (string.IsNullOrWhiteSpace(aiSettings.ApiKey) || aiSettings.ApiKey == "PLACEHOLDER") + // Register DB Context Factory for multi-threaded/asynchronous safety in Blazor + services.AddDbContextFactory(options => { - Console.WriteLine("[Infrastructure] WARNING: AI API Key is missing or placeholder!"); - } - - services.AddResiliencePipeline("ai-retry", builder => - { - builder.AddRetry(new RetryStrategyOptions + if (connectionString.Contains("Host=")) { - ShouldHandle = new PredicateBuilder().Handle(ex => - ex.Message.Contains("429") || ex.Message.Contains("Too Many Requests") || ex.Message.Contains("quota")), - BackoffType = DelayBackoffType.Exponential, - UseJitter = true, - MaxRetryAttempts = aiSettings.RetryAttempts, - Delay = TimeSpan.FromSeconds(2) - }); + options.UseNpgsql(connectionString, o => o.UseVector()); + } + else + { + options.UseSqlite(connectionString); + } }); - services.AddChatClient(new GeminiChatClient(new GeminiClientOptions - { - ApiKey = aiSettings.ApiKey, - ModelId = aiSettings.Model - })); - - services.AddEmbeddingGenerator(new GeminiEmbeddingGenerator(new GeminiClientOptions + // Register Scoped Context for traditional usage + services.AddDbContext(options => { - ApiKey = aiSettings.ApiKey, - ModelId = aiSettings.EmbeddingModel ?? "text-embedding-004" - })); + if (connectionString.Contains("Host=")) + { + options.UseNpgsql(connectionString, o => o.UseVector()); + } + else + { + options.UseSqlite(connectionString); + } + }); + // Identity Configuration + services.AddAuthorization(options => + { + options.AddPolicy("TokenLimitPolicy", policy => + policy.Requirements.Add(new TokenLimitRequirement())); + }); + + services.AddScoped(); + + // Services + services.AddScoped(); + services.AddScoped(); services.AddScoped(); - services.AddTransient(); + services.AddScoped(); + services.AddSingleton(); - services.AddAuthorizationCore(options => - { - options.AddPolicy("ProUser", policy => policy.Requirements.Add(new ProUserRequirement())); - }); - - services.AddScoped(); - - services.AddScoped(); + // Handlers (MediatR) + services.AddScoped, UpdateReadingProgressCommandHandler>(); return services; } - - public static System.Reflection.Assembly Assembly => typeof(DependencyInjection).Assembly; } - -public interface IInfrastructureMarker { } -internal class InfrastructureMarker : IInfrastructureMarker { }