Files
CBDDC/src/ZB.MOM.WW.CBDDC.Persistence/Surreal/CBDDCSurrealEmbeddedExtensions.cs
Joseph Doherty 8e97061ab8
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m14s
Implement in-process multi-dataset sync isolation across core, network, persistence, and tests
2026-02-22 11:58:34 -05:00

133 lines
6.0 KiB
C#

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using ZB.MOM.WW.CBDDC.Core;
using ZB.MOM.WW.CBDDC.Core.Network;
using SurrealDb.Net;
using ZB.MOM.WW.CBDDC.Core.Storage;
using ZB.MOM.WW.CBDDC.Core.Sync;
namespace ZB.MOM.WW.CBDDC.Persistence.Surreal;
/// <summary>
/// Extension methods for configuring embedded Surreal persistence for CBDDC.
/// </summary>
public static class CBDDCSurrealEmbeddedExtensions
{
/// <summary>
/// Adds embedded Surreal infrastructure to CBDDC and registers a document store implementation.
/// </summary>
/// <typeparam name="TDocumentStore">The concrete document store implementation.</typeparam>
/// <param name="services">The service collection to add services to.</param>
/// <param name="optionsFactory">Factory used to build embedded Surreal options.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddCBDDCSurrealEmbedded<TDocumentStore>(
this IServiceCollection services,
Func<IServiceProvider, CBDDCSurrealEmbeddedOptions> optionsFactory)
where TDocumentStore : class, IDocumentStore
{
RegisterCoreServices(services, optionsFactory);
services.TryAddSingleton<IDocumentStore, TDocumentStore>();
return services;
}
/// <summary>
/// Adds embedded Surreal infrastructure to CBDDC without registering store implementations.
/// </summary>
/// <param name="services">The service collection to add services to.</param>
/// <param name="optionsFactory">Factory used to build embedded Surreal options.</param>
/// <returns>The service collection for chaining.</returns>
/// <remarks>
/// Register store implementations separately when they become available.
/// </remarks>
public static IServiceCollection AddCBDDCSurrealEmbedded(
this IServiceCollection services,
Func<IServiceProvider, CBDDCSurrealEmbeddedOptions> optionsFactory)
{
RegisterCoreServices(services, optionsFactory);
return services;
}
/// <summary>
/// Registers dataset synchronization options for a Surreal-backed dataset pipeline.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="datasetId">The dataset identifier.</param>
/// <param name="configure">Optional per-dataset option overrides.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddCBDDCSurrealEmbeddedDataset(
this IServiceCollection services,
string datasetId,
Action<DatasetSyncOptions>? configure = null)
{
if (services == null) throw new ArgumentNullException(nameof(services));
var options = new DatasetSyncOptions
{
DatasetId = DatasetId.Normalize(datasetId),
Enabled = true
};
configure?.Invoke(options);
options.DatasetId = DatasetId.Normalize(options.DatasetId);
services.AddSingleton(options);
return services;
}
/// <summary>
/// Registers dataset synchronization options for a Surreal-backed dataset pipeline.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="configure">Configuration delegate for dataset options.</param>
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddCBDDCSurrealEmbeddedDataset(
this IServiceCollection services,
Action<DatasetSyncOptions> configure)
{
if (configure == null) throw new ArgumentNullException(nameof(configure));
var options = new DatasetSyncOptions
{
DatasetId = DatasetId.Primary,
Enabled = true
};
configure(options);
return services.AddCBDDCSurrealEmbeddedDataset(options.DatasetId, configured =>
{
configured.Enabled = options.Enabled;
configured.SyncLoopDelay = options.SyncLoopDelay;
configured.MaxPeersPerCycle = options.MaxPeersPerCycle;
configured.MaxEntriesPerCycle = options.MaxEntriesPerCycle;
configured.MaintenanceIntervalOverride = options.MaintenanceIntervalOverride;
configured.InterestingCollections = options.InterestingCollections.ToList();
});
}
private static void RegisterCoreServices(
IServiceCollection services,
Func<IServiceProvider, CBDDCSurrealEmbeddedOptions> optionsFactory)
{
if (services == null) throw new ArgumentNullException(nameof(services));
if (optionsFactory == null) throw new ArgumentNullException(nameof(optionsFactory));
services.TryAddSingleton(optionsFactory);
services.TryAddSingleton<ICBDDCSurrealEmbeddedClient, CBDDCSurrealEmbeddedClient>();
services.TryAddSingleton<ISurrealDbClient>(sp => sp.GetRequiredService<ICBDDCSurrealEmbeddedClient>().Client);
services.TryAddSingleton<ICBDDCSurrealSchemaInitializer, CBDDCSurrealSchemaInitializer>();
services.TryAddSingleton<ICBDDCSurrealReadinessProbe, CBDDCSurrealReadinessProbe>();
services.TryAddSingleton<ISurrealCdcCheckpointPersistence, SurrealCdcCheckpointPersistence>();
services.TryAddSingleton<IConflictResolver, LastWriteWinsConflictResolver>();
services.TryAddSingleton<IVectorClockService, VectorClockService>();
services.TryAddSingleton<IPeerConfigurationStore, SurrealPeerConfigurationStore>();
services.TryAddSingleton<IPeerOplogConfirmationStore, SurrealPeerOplogConfirmationStore>();
services.TryAddSingleton<ISnapshotMetadataStore, SurrealSnapshotMetadataStore>();
services.TryAddSingleton<IDocumentMetadataStore, SurrealDocumentMetadataStore>();
services.TryAddSingleton<IOplogStore, SurrealOplogStore>();
// SnapshotStore registration matches the other provider extension patterns.
services.TryAddSingleton<ISnapshotService, SnapshotStore>();
}
}