Add XML docs required by CommentChecker fixes
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m13s

This commit is contained in:
Joseph Doherty
2026-02-23 04:39:25 -05:00
parent cce24fa8f3
commit 6c4714f666
15 changed files with 444 additions and 15 deletions

View File

@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
using ZB.MOM.WW.CBDDC.Core.Network;
using ZB.MOM.WW.CBDDC.Network;
using ZB.MOM.WW.CBDDC.Network.Security;
using ZB.MOM.WW.CBDDC.Persistence.Lmdb;
using ZB.MOM.WW.CBDDC.Persistence.Surreal;
using ZB.MOM.WW.CBDDC.Sample.Console;
@@ -15,6 +16,18 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
private readonly string _workDir;
private bool _started;
/// <summary>
/// Gets the active EF/Core context for generated users.
/// </summary>
public SampleDbContext Context { get; }
/// <summary>
/// Creates and initializes a benchmark peer node.
/// </summary>
/// <param name="serviceProvider">Service provider containing node dependencies.</param>
/// <param name="node">Benchmark node abstraction.</param>
/// <param name="context">Live data context used by the benchmark.</param>
/// <param name="workDir">Temporary working directory for this node.</param>
private BenchmarkPeerNode(
ServiceProvider serviceProvider,
ICBDDCNode node,
@@ -27,8 +40,13 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
_workDir = workDir;
}
public SampleDbContext Context { get; }
/// <summary>
/// Creates and starts a benchmark peer node from configuration.
/// </summary>
/// <param name="nodeId">Unique peer identifier.</param>
/// <param name="tcpPort">Local TCP port for the node.</param>
/// <param name="authToken">Authentication token shared across peers.</param>
/// <param name="knownPeers">Known peers to connect to at startup.</param>
public static BenchmarkPeerNode Create(
string nodeId,
int tcpPort,
@@ -58,7 +76,13 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
services.AddSingleton<ICBDDCSurrealSchemaInitializer, SampleSurrealSchemaInitializer>();
services.AddSingleton<SampleDbContext>();
services.AddCBDDCCore()
bool useLmdb = GetBoolEnv("CBDDC_BENCH_USE_LMDB", defaultValue: true);
bool dualWrite = GetBoolEnv("CBDDC_BENCH_DUAL_WRITE", defaultValue: true);
bool preferLmdbReads = GetBoolEnv("CBDDC_BENCH_PREFER_LMDB_READS", defaultValue: true);
bool enableShadowValidation = GetBoolEnv("CBDDC_BENCH_SHADOW_READ_VALIDATE", defaultValue: false);
int reconcileIntervalMs = GetIntEnv("CBDDC_BENCH_RECONCILE_INTERVAL_MS", defaultValue: 0);
var registration = services.AddCBDDCCore()
.AddCBDDCSurrealEmbedded<SampleDocumentStore>(_ => new CBDDCSurrealEmbeddedOptions
{
Endpoint = "rocksdb://local",
@@ -72,8 +96,27 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
PollingInterval = TimeSpan.FromMilliseconds(50),
EnableLiveSelectAccelerator = true
}
})
.AddCBDDCNetwork<StaticPeerNodeConfigurationProvider>(false);
});
if (useLmdb)
registration.AddCBDDCLmdbOplog(
_ => new LmdbOplogOptions
{
EnvironmentPath = Path.Combine(workDir, "oplog-lmdb"),
MapSizeBytes = 256L * 1024 * 1024,
MaxDatabases = 16,
PruneBatchSize = 512
},
flags =>
{
flags.UseLmdbOplog = true;
flags.DualWriteOplog = dualWrite;
flags.PreferLmdbReads = preferLmdbReads;
flags.EnableReadShadowValidation = enableShadowValidation;
flags.ReconciliationInterval = TimeSpan.FromMilliseconds(Math.Max(0, reconcileIntervalMs));
});
registration.AddCBDDCNetwork<StaticPeerNodeConfigurationProvider>(false);
// Benchmark runs use explicit known peers; disable UDP discovery and handshake overhead.
services.AddSingleton<IDiscoveryService, PassiveDiscoveryService>();
@@ -86,6 +129,9 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
return new BenchmarkPeerNode(provider, node, context, workDir);
}
/// <summary>
/// Starts the node asynchronously.
/// </summary>
public async Task StartAsync()
{
if (_started) return;
@@ -93,6 +139,9 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
_started = true;
}
/// <summary>
/// Stops the node asynchronously.
/// </summary>
public async Task StopAsync()
{
if (!_started) return;
@@ -111,22 +160,37 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
_started = false;
}
/// <summary>
/// Inserts or updates a user record.
/// </summary>
/// <param name="user">User payload.</param>
public async Task UpsertUserAsync(User user)
{
await Context.Users.UpdateAsync(user);
await Context.SaveChangesAsync();
}
/// <summary>
/// Returns whether a user identifier exists.
/// </summary>
/// <param name="userId">Target user identifier.</param>
public bool ContainsUser(string userId)
{
return Context.Users.Find(u => u.Id == userId).Any();
}
/// <summary>
/// Counts user identifiers matching the provided prefix.
/// </summary>
/// <param name="prefix">User identifier prefix.</param>
public int CountUsersWithPrefix(string prefix)
{
return Context.Users.FindAll().Count(u => u.Id.StartsWith(prefix, StringComparison.Ordinal));
}
/// <summary>
/// Disposes the node and any unmanaged resources.
/// </summary>
public async ValueTask DisposeAsync()
{
try
@@ -156,18 +220,43 @@ internal sealed class BenchmarkPeerNode : IAsyncDisposable
}
}
private static bool GetBoolEnv(string key, bool defaultValue)
{
string? raw = Environment.GetEnvironmentVariable(key);
if (string.IsNullOrWhiteSpace(raw)) return defaultValue;
if (bool.TryParse(raw, out bool parsed)) return parsed;
return defaultValue;
}
private static int GetIntEnv(string key, int defaultValue)
{
string? raw = Environment.GetEnvironmentVariable(key);
if (string.IsNullOrWhiteSpace(raw)) return defaultValue;
if (int.TryParse(raw, out int parsed)) return parsed;
return defaultValue;
}
private sealed class PassiveDiscoveryService : IDiscoveryService
{
/// <summary>
/// Gets the current list of active peers.
/// </summary>
public IEnumerable<PeerNode> GetActivePeers()
{
return Array.Empty<PeerNode>();
}
/// <summary>
/// Starts discovery.
/// </summary>
public Task Start()
{
return Task.CompletedTask;
}
/// <summary>
/// Stops discovery.
/// </summary>
public Task Stop()
{
return Task.CompletedTask;