using Femto.Common.Infrastructure; using Femto.Common.Infrastructure.Outbox; using Femto.Common.Integration; using Femto.Modules.Auth.Data; using Femto.Modules.Auth.Infrastructure; using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Quartz; namespace Femto.Modules.Auth.Application; public static class AuthStartup { public static void InitializeAuthenticationModule(this IServiceCollection rootContainer, string connectionString, IEventBus eventBus) { var hostBuilder = Host.CreateDefaultBuilder(); hostBuilder.ConfigureServices(services => ConfigureServices(services, connectionString, eventBus)); var host = hostBuilder.Build(); rootContainer.AddScoped(_ => new AuthModule(host)); rootContainer.AddHostedService(services => new AuthApplication(host)); eventBus.Subscribe((evt, cancellationToken) => EventSubscriber(evt, host.Services, cancellationToken)); } private static void ConfigureServices(IServiceCollection services, string connectionString, IEventPublisher publisher) { services.AddDbContext(builder => { builder.UseNpgsql(connectionString); builder.UseSnakeCaseNamingConvention(); }); services.AddQuartzHostedService(options => { options.WaitForJobsToComplete = true; }); services.AddOutbox(); services.AddMediatR(c => c.RegisterServicesFromAssembly(typeof(AuthStartup).Assembly)); services.AddDbContext(builder => { builder.UseNpgsql(); builder.UseSnakeCaseNamingConvention(); var loggerFactory = LoggerFactory.Create(b => { }); builder.UseLoggerFactory(loggerFactory); }); services.ConfigureDomainServices(); services.AddSingleton(publisher); } private static async Task EventSubscriber( IEvent evt, IServiceProvider provider, CancellationToken cancellationToken ) { using var scope = provider.CreateScope(); var context = scope.ServiceProvider.GetRequiredService(); var logger = scope.ServiceProvider.GetRequiredService>(); var publisher = scope.ServiceProvider.GetRequiredService(); IEventHandler? handler = evt switch { _ => null, }; if (handler is null) return; await handler.Handle(evt, cancellationToken); if (context.ChangeTracker.HasChanges()) { await context.EmitDomainEvents(logger, publisher, cancellationToken); await context.SaveChangesAsync(cancellationToken); } } }