//
// 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();
}
}