Files
git.stella-ops.org/src/AirGap/__Libraries/StellaOps.AirGap.Sync/AirGapSyncServiceCollectionExtensions.cs

154 lines
6.1 KiB
C#

// <copyright file="AirGapSyncServiceCollectionExtensions.cs" company="StellaOps">
// Copyright (c) StellaOps. Licensed under AGPL-3.0-or-later.
// </copyright>
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;
/// <summary>
/// Extension methods for registering air-gap sync services.
/// </summary>
public static class AirGapSyncServiceCollectionExtensions
{
/// <summary>
/// Adds air-gap sync services to the service collection.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="nodeId">The node identifier for this instance.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddAirGapSyncServices(
this IServiceCollection services,
string nodeId)
{
ArgumentException.ThrowIfNullOrWhiteSpace(nodeId);
// Core services
services.TryAddSingleton<IConflictResolver, ConflictResolver>();
services.TryAddSingleton<IHlcMergeService, HlcMergeService>();
services.TryAddSingleton<IAirGapBundleImporter, AirGapBundleImporter>();
// Register in-memory HLC state store for offline operation
services.TryAddSingleton<IHlcStateStore, InMemoryHlcStateStore>();
// Register HLC clock with node ID
services.TryAddSingleton<IHybridLogicalClock>(sp =>
{
var timeProvider = sp.GetService<TimeProvider>() ?? TimeProvider.System;
var stateStore = sp.GetRequiredService<IHlcStateStore>();
var logger = sp.GetRequiredService<ILogger<HybridLogicalClock.HybridLogicalClock>>();
return new HybridLogicalClock.HybridLogicalClock(timeProvider, nodeId, stateStore, logger);
});
// Register deterministic GUID provider
services.TryAddSingleton<IGuidProvider>(SystemGuidProvider.Instance);
// File-based store (can be overridden)
services.TryAddSingleton<IOfflineJobLogStore, FileBasedOfflineJobLogStore>();
// Offline HLC manager
services.TryAddSingleton<IOfflineHlcManager, OfflineHlcManager>();
// Bundle exporter
services.TryAddSingleton<IAirGapBundleExporter, AirGapBundleExporter>();
// Bundle DSSE signer (OMP-010)
services.TryAddSingleton<IAirGapBundleDsseSigner, AirGapBundleDsseSigner>();
return services;
}
/// <summary>
/// Adds air-gap sync services with custom options.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="nodeId">The node identifier for this instance.</param>
/// <param name="configureOptions">Action to configure file-based store options.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddAirGapSyncServices(
this IServiceCollection services,
string nodeId,
Action<FileBasedOfflineJobLogStoreOptions> configureOptions)
{
// Configure file-based store options
services.Configure(configureOptions);
return services.AddAirGapSyncServices(nodeId);
}
/// <summary>
/// Adds the air-gap sync service for importing bundles to the central scheduler.
/// </summary>
/// <param name="services">The service collection.</param>
/// <returns>The service collection for chaining.</returns>
/// <remarks>
/// This requires ISyncSchedulerLogRepository to be registered separately,
/// as it depends on the Scheduler.Persistence module.
/// </remarks>
public static IServiceCollection AddAirGapSyncImportService(this IServiceCollection services)
{
services.TryAddScoped<IAirGapSyncService, AirGapSyncService>();
return services;
}
/// <summary>
/// Adds file-based transport for job sync bundles.
/// </summary>
/// <param name="services">The service collection.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddFileBasedJobSyncTransport(this IServiceCollection services)
{
services.TryAddSingleton<IJobSyncTransport, FileBasedJobSyncTransport>();
return services;
}
/// <summary>
/// Adds file-based transport for job sync bundles with custom options.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="configureOptions">Action to configure transport options.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddFileBasedJobSyncTransport(
this IServiceCollection services,
Action<FileBasedJobSyncTransportOptions> configureOptions)
{
services.Configure(configureOptions);
return services.AddFileBasedJobSyncTransport();
}
/// <summary>
/// Adds Router-based transport for job sync bundles.
/// </summary>
/// <param name="services">The service collection.</param>
/// <returns>The service collection for chaining.</returns>
/// <remarks>
/// Requires IRouterJobSyncClient to be registered separately.
/// </remarks>
public static IServiceCollection AddRouterJobSyncTransport(this IServiceCollection services)
{
services.TryAddSingleton<IJobSyncTransport, RouterJobSyncTransport>();
return services;
}
/// <summary>
/// Adds Router-based transport for job sync bundles with custom options.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="configureOptions">Action to configure transport options.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddRouterJobSyncTransport(
this IServiceCollection services,
Action<RouterJobSyncTransportOptions> configureOptions)
{
services.Configure(configureOptions);
return services.AddRouterJobSyncTransport();
}
}