Files
Deal/src/core/Deal.Infrastructure/ServiceCollectionExtensions.cs
T
stepan d172b6408b Внедрить фабрики объектов вместо прямого new
Создание сервисов с порт-интерфейсом перенесено в IXxxFactory:
шифр секретов, хранилище лимитов, ИИ-классификатор, ИИ-инструменты,
файловое хранилище (Local/MinIO). Регистраторы и DiscoveryWorkerService
больше не создают реализации напрямую. Добавлен тест FileStorageFactory.
2026-09-13 03:41:39 +03:00

157 lines
6.9 KiB
C#

using Deal.Contracts.Integrations.Abstractions;
using Deal.Infrastructure.Integrations.Abstractions;
using Deal.Infrastructure.Integrations.Models;
using Deal.Infrastructure.Integrations.Options;
using Deal.Infrastructure.Integrations.Services;
using Deal.Infrastructure.Integrations.Sources;
using Deal.Infrastructure.Persistence;
using Deal.Infrastructure.Persistence.Abstractions;
using Deal.Infrastructure.Persistence.Repositories;
using Deal.Infrastructure.Persistence.Services;
using Deal.Infrastructure.Security;
using Deal.Infrastructure.Security.Abstractions;
using Deal.Infrastructure.Security.Services;
using Deal.Infrastructure.Services;
using Deal.Infrastructure.Tenancy;
using Deal.Modules.Cards.Application.Abstractions;
using Deal.Modules.Cards.Application.Sources;
using Deal.Modules.Discovery.Application.Abstractions;
using Deal.Modules.Kanban.Application.Abstractions;
using Deal.Modules.Pipeline.Application.Abstractions;
using Deal.Modules.Settings.Application.Abstractions;
using Deal.Modules.Telegram.Application;
using Deal.Modules.Tenants.Application.Abstractions;
using Deal.Modules.Tenants.Application.Models;
using Deal.SharedKernel.Tenants.Abstractions;
using Microsoft.Extensions.DependencyInjection;
namespace Deal.Infrastructure;
/// <summary>
/// DI-регистрация адаптеров персистентности Deal.Infrastructure.
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Регистрирует EF-адаптеры портов модулей
/// </summary>
/// <param name="tenantLimitDefaults">Дефолт-бюджет лениво создаваемых строк tenant_limits. Передаётся из конфигурации/env DEAL_DEFAULT_AI_BUDGET в Program.cs.</param>
public static IServiceCollection AddDealPersistence(this IServiceCollection services, TokenLimitDefaults? tenantLimitDefaults = null)
{
services.AddScoped<IAuthStore, AuthStore>();
services.AddScoped<IOperatorAuthStore, OperatorAuthStore>();
services.AddScoped<ITenantRepository, TenantRepository>();
services.AddScoped<IAuditLogStore, AuditLogStore>();
services.AddScoped<ITokenUsageEventStore, TokenUsageEventStore>();
services.AddScoped<IInviteStore, InviteStore>();
services.AddSingleton(tenantLimitDefaults ?? TokenBudgetDefaults.Default);
services.AddScoped<ITenantLimitStoreFactory, TenantLimitStoreFactory>();
services.AddScoped<ITenantLimitStore>(provider => provider.GetRequiredService<ITenantLimitStoreFactory>().Create());
services.AddScoped<IRateLimitCounterStore, RateLimitCounterStore>();
services.AddScoped<ISettingsStore, SettingsStore>();
services.AddScoped<IGlobalSettingsStore, GlobalSettingsStore>();
services.AddScoped<ICardStore, KanbanStore>();
services.AddScoped<ISourceContentProvider, TelegramSourceContentProvider>();
services.AddScoped<IPipelineStore, PipelineStore>();
services.AddScoped<IMlLearningStore, MlLearningStore>();
services.AddScoped<ITelegramStore, TelegramStore>();
services.AddScoped<IDiscoveryStore, DiscoveryStore>();
services.AddScoped<ITenantProvisioner, TenantProvisioningService>();
services.AddScoped<TenantSchemaMigrationService>();
services.AddScoped<ICardMover, CardMover>();
return services;
}
/// <summary>
/// Регистрирует адаптеры внешних интеграций
/// </summary>
/// <param name="mlOptions">Конфигурация секции <c>Services:Ml</c> — выбор реализации IMlClient.</param>
/// <param name="aiOptions">Конфигурация секции <c>Services:Ai</c> — выбор реализации IAiClassifier/IAiTools.</param>
/// <param name="telegramOptions">Конфигурация секции <c>Services:Telegram</c> — выбор реализации ITelegramGateway.</param>
public static IServiceCollection AddDealIntegrations(
this IServiceCollection services,
MlServiceOptions mlOptions,
AiServiceOptions aiOptions,
TelegramServiceOptions telegramOptions,
MtlsCertificates? mtlsCertificates = null)
{
services.AddScoped<TokenUsageRecorder>();
if (mlOptions.UseLocal)
{
services.AddScoped<IMlClient, LocalMlClient>();
}
else
{
services.AddSingleton(new MlGrpcConnection(mlOptions, mtlsCertificates));
services.AddSingleton<MlStatusCache>();
services.AddScoped<GrpcMlClient>();
services.AddScoped<IMlClient>(provider => provider.GetRequiredService<GrpcMlClient>());
services.AddScoped<IMlTrainClient>(provider => provider.GetRequiredService<GrpcMlClient>());
}
services.AddScoped<IColumnSuggester, LocalColumnSuggester>();
if (aiOptions.UseLocal)
{
services.AddScoped<IAiClassifier, LocalAiClassifier>();
services.AddScoped<IAiTools, LocalAiTools>();
}
else
{
services.AddSingleton(new AiGrpcConnection(aiOptions, mtlsCertificates));
services.AddScoped<AiProviderConfigBuilder>();
services.AddScoped<GrpcAiClassifier>();
services.AddScoped<LocalAiClassifier>();
services.AddScoped<IAiClassifierFactory, AiClassifierFactory>();
services.AddScoped<IAiClassifier>(provider => provider.GetRequiredService<IAiClassifierFactory>().Create());
services.AddScoped<GrpcAiTools>();
services.AddScoped<IAiToolsFactory, AiToolsFactory>();
services.AddScoped<IAiTools>(provider => provider.GetRequiredService<IAiToolsFactory>().Create());
}
if (telegramOptions.UseLocal)
{
services.AddSingleton<ITelegramGateway, LocalTelegramGateway>();
}
else
{
services.AddSingleton(new TelegramGrpcConnection(telegramOptions, mtlsCertificates));
services.AddScoped<GrpcTelegramClient>();
services.AddScoped<ITelegramGateway>(provider => provider.GetRequiredService<GrpcTelegramClient>());
}
return services;
}
/// <summary>
/// Регистрирует сервисы шифрования секретов
/// </summary>
/// <param name="contentRootPath">ContentRoot приложения — каталог по умолчанию для файла-ключа data/encryption.key.</param>
public static IServiceCollection AddDealSecurity(this IServiceCollection services, string contentRootPath)
{
EncryptionKeyProvider keyProvider = new(contentRootPath);
services.AddSingleton(keyProvider);
services.AddSingleton<ISecretCipherFactory, SecretCipherFactory>();
services.AddSingleton<ISecretCipher>(provider => provider.GetRequiredService<ISecretCipherFactory>().Create());
return services;
}
}