using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using MongoDB.Driver; using StellaOps.Concelier.Core.Jobs; using StellaOps.Concelier.Storage.Mongo.Advisories; using StellaOps.Concelier.Storage.Mongo.Aliases; using StellaOps.Concelier.Storage.Mongo.ChangeHistory; using StellaOps.Concelier.Storage.Mongo.Documents; using StellaOps.Concelier.Storage.Mongo.Dtos; using StellaOps.Concelier.Storage.Mongo.Raw; using StellaOps.Concelier.Core.Raw; using StellaOps.Concelier.Storage.Mongo.Exporting; using StellaOps.Concelier.Storage.Mongo.JpFlags; using StellaOps.Concelier.Storage.Mongo.MergeEvents; using StellaOps.Concelier.Storage.Mongo.Conflicts; using StellaOps.Concelier.Storage.Mongo.PsirtFlags; using StellaOps.Concelier.Storage.Mongo.Statements; using StellaOps.Concelier.Storage.Mongo.Events; using StellaOps.Concelier.Core.Events; using StellaOps.Concelier.Storage.Mongo.Migrations; using StellaOps.Concelier.Storage.Mongo.Observations; using StellaOps.Concelier.Core.Observations; using StellaOps.Concelier.Storage.Mongo.Linksets; using StellaOps.Concelier.Storage.Mongo.Orchestrator; using StellaOps.Concelier.Storage.Mongo.PolicyDelta; using StellaOps.Concelier.Core.Linksets; namespace StellaOps.Concelier.Storage.Mongo; public static class ServiceCollectionExtensions { public static IServiceCollection AddMongoStorage(this IServiceCollection services, Action configureOptions) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(configureOptions); // In unit/integration tests we bypass Mongo wiring entirely; callers may inject fakes. var isTesting = string.Equals( Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT"), "Testing", StringComparison.OrdinalIgnoreCase); var bypass = string.Equals( Environment.GetEnvironmentVariable("CONCELIER_BYPASS_MONGO"), "1", StringComparison.OrdinalIgnoreCase); if (isTesting || bypass) { return services; } services.AddOptions() .Configure(configureOptions) .PostConfigure(static options => { // Normal path: enforce validity. options.EnsureValid(); }); services.TryAddSingleton(TimeProvider.System); services.AddSingleton(static sp => { var options = sp.GetRequiredService>().Value; return new MongoClient(options.ConnectionString); }); services.AddSingleton(static sp => { var options = sp.GetRequiredService>().Value; var client = sp.GetRequiredService(); var settings = new MongoDatabaseSettings { ReadConcern = ReadConcern.Majority, WriteConcern = WriteConcern.WMajority, ReadPreference = ReadPreference.PrimaryPreferred, }; var database = client.GetDatabase(options.GetDatabaseName(), settings); var writeConcern = database.Settings.WriteConcern.With(wTimeout: options.CommandTimeout); return database.WithWriteConcern(writeConcern); }); services.AddScoped(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(sp => { var options = sp.GetRequiredService>().Value; if (options.Enabled && string.Equals(options.Transport, "nats", StringComparison.OrdinalIgnoreCase)) { return sp.GetRequiredService(); } return NullAdvisoryObservationEventTransport.Instance; }); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(sp => sp.GetRequiredService()); services.AddSingleton(sp => sp.GetRequiredService()); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.TryAddSingleton(); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.Jobs); }); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.Locks); }); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.AdvisoryObservations); }); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.AdvisoryObservationEvents); }); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.OrchestratorRegistry); }); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.OrchestratorCommands); }); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.OrchestratorHeartbeats); }); services.AddSingleton>(static sp => { var database = sp.GetRequiredService(); return database.GetCollection(MongoStorageDefaults.Collections.AdvisoryLinksets); }); services.AddHostedService(); services.AddHostedService(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); return services; } }