save checkpoint
This commit is contained in:
@@ -3,7 +3,10 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Npgsql;
|
||||
using StellaOps.HybridLogicalClock;
|
||||
using StellaOps.Eventing.Signing;
|
||||
using StellaOps.Eventing.Storage;
|
||||
using StellaOps.Eventing.Telemetry;
|
||||
@@ -42,12 +45,26 @@ public static class ServiceCollectionExtensions
|
||||
|
||||
// Register event store based on configuration
|
||||
var options = configuration.GetSection(EventingOptions.SectionName).Get<EventingOptions>();
|
||||
TryAddHybridLogicalClock(services, options?.ServiceName);
|
||||
|
||||
if (options?.UseInMemoryStore == true)
|
||||
{
|
||||
services.TryAddSingleton<ITimelineEventStore, InMemoryTimelineEventStore>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.TryAddSingleton(sp =>
|
||||
{
|
||||
var configuredOptions = sp.GetRequiredService<IOptions<EventingOptions>>().Value;
|
||||
if (string.IsNullOrWhiteSpace(configuredOptions.ConnectionString))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Eventing:ConnectionString must be configured when Eventing:UseInMemoryStore is false.");
|
||||
}
|
||||
|
||||
return NpgsqlDataSource.Create(configuredOptions.ConnectionString);
|
||||
});
|
||||
|
||||
services.TryAddSingleton<ITimelineEventStore, PostgresTimelineEventStore>();
|
||||
}
|
||||
|
||||
@@ -84,6 +101,7 @@ public static class ServiceCollectionExtensions
|
||||
.ValidateOnStart();
|
||||
|
||||
services.TryAddSingleton(TimeProvider.System);
|
||||
TryAddHybridLogicalClock(services, serviceName);
|
||||
|
||||
// Register NpgsqlDataSource
|
||||
services.TryAddSingleton(_ => NpgsqlDataSource.Create(connectionString));
|
||||
@@ -119,6 +137,7 @@ public static class ServiceCollectionExtensions
|
||||
.ValidateOnStart();
|
||||
|
||||
services.TryAddSingleton(TimeProvider.System);
|
||||
TryAddHybridLogicalClock(services, serviceName);
|
||||
services.TryAddSingleton<ITimelineEventStore, InMemoryTimelineEventStore>();
|
||||
services.TryAddSingleton<ITimelineEventEmitter, TimelineEventEmitter>();
|
||||
services.TryAddSingleton<EventingTelemetry>();
|
||||
@@ -138,4 +157,33 @@ public static class ServiceCollectionExtensions
|
||||
services.TryAddSingleton<IEventSigner, TSigner>();
|
||||
return services;
|
||||
}
|
||||
|
||||
private static void TryAddHybridLogicalClock(IServiceCollection services, string? nodeId)
|
||||
{
|
||||
var resolvedNodeId = ResolveNodeId(nodeId);
|
||||
|
||||
services.TryAddSingleton<IHlcStateStore, InMemoryHlcStateStore>();
|
||||
services.TryAddSingleton<IHybridLogicalClock>(sp =>
|
||||
{
|
||||
var timeProvider = sp.GetRequiredService<TimeProvider>();
|
||||
var stateStore = sp.GetRequiredService<IHlcStateStore>();
|
||||
var logger = sp.GetRequiredService<ILogger<StellaOps.HybridLogicalClock.HybridLogicalClock>>();
|
||||
|
||||
return new StellaOps.HybridLogicalClock.HybridLogicalClock(
|
||||
timeProvider,
|
||||
resolvedNodeId,
|
||||
stateStore,
|
||||
logger);
|
||||
});
|
||||
}
|
||||
|
||||
private static string ResolveNodeId(string? nodeId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(nodeId))
|
||||
{
|
||||
return "eventing";
|
||||
}
|
||||
|
||||
return nodeId.Trim().Replace(' ', '-').ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StellaOps.Eventing.Storage;
|
||||
using StellaOps.HybridLogicalClock;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Eventing.Tests;
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class ServiceCollectionExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddStellaOpsEventing_InMemoryStore_RegistersEmitterAndClock()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Eventing:ServiceName"] = "TimelineTests",
|
||||
["Eventing:UseInMemoryStore"] = "true",
|
||||
})
|
||||
.Build();
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
|
||||
services.AddStellaOpsEventing(configuration);
|
||||
|
||||
using var provider = services.BuildServiceProvider();
|
||||
|
||||
provider.GetRequiredService<IHybridLogicalClock>().Should().NotBeNull();
|
||||
provider.GetRequiredService<ITimelineEventStore>().Should().BeOfType<InMemoryTimelineEventStore>();
|
||||
provider.GetRequiredService<ITimelineEventEmitter>().Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddStellaOpsEventing_PostgresStore_RegistersEmitterClockAndStore()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Eventing:ServiceName"] = "TimelineTests",
|
||||
["Eventing:UseInMemoryStore"] = "false",
|
||||
["Eventing:ConnectionString"] = "Host=localhost;Port=5432;Database=timeline;Username=postgres;Password=postgres",
|
||||
})
|
||||
.Build();
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
|
||||
services.AddStellaOpsEventing(configuration);
|
||||
|
||||
using var provider = services.BuildServiceProvider();
|
||||
|
||||
provider.GetRequiredService<IHybridLogicalClock>().Should().NotBeNull();
|
||||
provider.GetRequiredService<ITimelineEventStore>().Should().BeOfType<PostgresTimelineEventStore>();
|
||||
provider.GetRequiredService<ITimelineEventEmitter>().Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user