// // Copyright (c) StellaOps. Licensed under AGPL-3.0-or-later. // using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using StellaOps.AirGap.Sync.Services; using StellaOps.AirGap.Sync.Stores; using StellaOps.AirGap.Sync.Transport; using StellaOps.Determinism; using StellaOps.HybridLogicalClock; namespace StellaOps.AirGap.Sync; /// /// Extension methods for registering air-gap sync services. /// public static class AirGapSyncServiceCollectionExtensions { /// /// Adds air-gap sync services to the service collection. /// /// The service collection. /// The node identifier for this instance. /// The service collection for chaining. public static IServiceCollection AddAirGapSyncServices( this IServiceCollection services, string nodeId) { ArgumentException.ThrowIfNullOrWhiteSpace(nodeId); // Core services services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); // Register in-memory HLC state store for offline operation services.TryAddSingleton(); // Register HLC clock with node ID services.TryAddSingleton(sp => { var timeProvider = sp.GetService() ?? TimeProvider.System; var stateStore = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); return new HybridLogicalClock.HybridLogicalClock(timeProvider, nodeId, stateStore, logger); }); // Register deterministic GUID provider services.TryAddSingleton(SystemGuidProvider.Instance); // File-based store (can be overridden) services.TryAddSingleton(); // Offline HLC manager services.TryAddSingleton(); // Bundle exporter services.TryAddSingleton(); // Bundle DSSE signer (OMP-010) services.TryAddSingleton(); return services; } /// /// Adds air-gap sync services with custom options. /// /// The service collection. /// The node identifier for this instance. /// Action to configure file-based store options. /// The service collection for chaining. public static IServiceCollection AddAirGapSyncServices( this IServiceCollection services, string nodeId, Action configureOptions) { // Configure file-based store options services.Configure(configureOptions); return services.AddAirGapSyncServices(nodeId); } /// /// Adds the air-gap sync service for importing bundles to the central scheduler. /// /// The service collection. /// The service collection for chaining. /// /// This requires ISyncSchedulerLogRepository to be registered separately, /// as it depends on the Scheduler.Persistence module. /// public static IServiceCollection AddAirGapSyncImportService(this IServiceCollection services) { services.TryAddScoped(); return services; } /// /// Adds file-based transport for job sync bundles. /// /// The service collection. /// The service collection for chaining. public static IServiceCollection AddFileBasedJobSyncTransport(this IServiceCollection services) { services.TryAddSingleton(); return services; } /// /// Adds file-based transport for job sync bundles with custom options. /// /// The service collection. /// Action to configure transport options. /// The service collection for chaining. public static IServiceCollection AddFileBasedJobSyncTransport( this IServiceCollection services, Action configureOptions) { services.Configure(configureOptions); return services.AddFileBasedJobSyncTransport(); } /// /// Adds Router-based transport for job sync bundles. /// /// The service collection. /// The service collection for chaining. /// /// Requires IRouterJobSyncClient to be registered separately. /// public static IServiceCollection AddRouterJobSyncTransport(this IServiceCollection services) { services.TryAddSingleton(); return services; } /// /// Adds Router-based transport for job sync bundles with custom options. /// /// The service collection. /// Action to configure transport options. /// The service collection for chaining. public static IServiceCollection AddRouterJobSyncTransport( this IServiceCollection services, Action configureOptions) { services.Configure(configureOptions); return services.AddRouterJobSyncTransport(); } }