using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Npgsql; using StellaOps.AirGap.Controller.Stores; using StellaOps.AirGap.Importer.Versioning; using StellaOps.AirGap.Persistence.Postgres; using StellaOps.AirGap.Persistence.Postgres.Repositories; using StellaOps.Infrastructure.Postgres.Options; namespace StellaOps.AirGap.Persistence.Extensions; /// /// Extension methods for configuring AirGap persistence services. /// public static class AirGapPersistenceExtensions { /// /// Adds AirGap PostgreSQL persistence services. /// public static IServiceCollection AddAirGapPersistence( this IServiceCollection services, IConfiguration configuration, string sectionName = "Postgres:AirGap") { services.Configure(sectionName, configuration.GetSection(sectionName)); services.AddSingleton(); services.AddHostedService(sp => CreateMigrationHost(sp)); services.AddScoped(); services.AddScoped(); return services; } /// /// Adds AirGap PostgreSQL persistence services with explicit options. /// public static IServiceCollection AddAirGapPersistence( this IServiceCollection services, Action configureOptions) { services.Configure(configureOptions); services.AddSingleton(); services.AddHostedService(sp => CreateMigrationHost(sp)); services.AddScoped(); services.AddScoped(); return services; } private static IHostedService CreateMigrationHost(IServiceProvider serviceProvider) { var options = serviceProvider.GetRequiredService>().Value; var schemaName = string.IsNullOrWhiteSpace(options.SchemaName) ? AirGapDataSource.DefaultSchemaName : options.SchemaName!; var connectionString = BuildMigrationConnectionString(options, schemaName); var logger = serviceProvider.GetRequiredService() .CreateLogger("Migration.AirGap.Persistence"); var lifetime = serviceProvider.GetRequiredService(); return new AirGapStartupMigrationHost( connectionString, schemaName, "AirGap.Persistence", typeof(AirGapDataSource).Assembly, logger, lifetime); } private static string BuildMigrationConnectionString(PostgresOptions options, string schemaName) { var builder = new NpgsqlConnectionStringBuilder(options.ConnectionString) { CommandTimeout = options.CommandTimeoutSeconds }; if (!string.IsNullOrWhiteSpace(schemaName)) { builder.SearchPath = $"{schemaName}, public"; } return builder.ConnectionString; } }