diff --git a/src/RoadRegistry.AdminHost/Infrastructure/Program.cs b/src/RoadRegistry.AdminHost/Infrastructure/Program.cs index 2cbd23f12..ec6b42354 100644 --- a/src/RoadRegistry.AdminHost/Infrastructure/Program.cs +++ b/src/RoadRegistry.AdminHost/Infrastructure/Program.cs @@ -28,7 +28,7 @@ protected Program() public static async Task Main(string[] args) { var roadRegistryHost = new RoadRegistryHostBuilder(args) - .ConfigureServices((hostContext, services) => services + .ConfigureServices((_, services) => services .AddTicketing() .AddEmailClient() .AddSingleton(sp => Dispatch.Using(Resolve.WhenEqualToMessage( @@ -58,11 +58,10 @@ public static async Task Main(string[] args) .AddRoadNetworkCommandQueue() .AddRoadNetworkEventWriter() .AddRoadRegistrySnapshot() - .AddRoadNetworkSnapshotStrategyOptions() .AddEditorContext() .AddProductContext() ) - .ConfigureContainer((hostContext, builder) => + .ConfigureContainer((_, builder) => { builder.RegisterModule(); builder.RegisterModule(); diff --git a/src/RoadRegistry.BackOffice.Api/Infrastructure/Startup.cs b/src/RoadRegistry.BackOffice.Api/Infrastructure/Startup.cs index ec9c915f9..9717fdfa1 100644 --- a/src/RoadRegistry.BackOffice.Api/Infrastructure/Startup.cs +++ b/src/RoadRegistry.BackOffice.Api/Infrastructure/Startup.cs @@ -18,8 +18,6 @@ namespace RoadRegistry.BackOffice.Api.Infrastructure; using Be.Vlaanderen.Basisregisters.Api; using Be.Vlaanderen.Basisregisters.Api.Exceptions; using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; -using Be.Vlaanderen.Basisregisters.BlobStore; -using Be.Vlaanderen.Basisregisters.BlobStore.Sql; using Be.Vlaanderen.Basisregisters.Shaperon.Geometries; using Behaviors; using Configuration; @@ -27,6 +25,7 @@ namespace RoadRegistry.BackOffice.Api.Infrastructure; using Core; using Editor.Schema; using Extensions; +using FeatureCompare.Readers; using FeatureToggles; using FluentValidation; using Framework; @@ -38,7 +37,6 @@ namespace RoadRegistry.BackOffice.Api.Infrastructure; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Formatters; -using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -57,14 +55,8 @@ namespace RoadRegistry.BackOffice.Api.Infrastructure; using Serilog.Extensions.Logging; using Snapshot.Handlers.Sqs; using SqlStreamStore; -using SystemHealthCheck; -using System; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using FeatureCompare.Readers; using Sync.MunicipalityRegistry; +using SystemHealthCheck; using SystemHealthCheck.HealthChecks; using ZipArchiveWriters.Cleaning; using DomainAssemblyMarker = BackOffice.Handlers.Sqs.DomainAssemblyMarker; @@ -75,12 +67,10 @@ public class Startup { private const string DatabaseTag = "db"; private readonly IConfiguration _configuration; - private readonly IWebHostEnvironment _webHostEnvironment; - public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment) + public Startup(IConfiguration configuration) { _configuration = configuration; - _webHostEnvironment = webHostEnvironment; } public void Configure( @@ -329,7 +319,6 @@ public void ConfigureServices(IServiceCollection services) .AddHealthCommandQueue() .AddRoadNetworkCommandQueue() .AddOrganizationCommandQueue() - .AddRoadNetworkSnapshotStrategyOptions() .AddSingleton(apiOptions) .Configure(_configuration) diff --git a/src/RoadRegistry.BackOffice/Configuration/RoadNetworkSnapshotStrategyOptions.cs b/src/RoadRegistry.BackOffice/Configuration/RoadNetworkSnapshotStrategyOptions.cs deleted file mode 100644 index 1b9a1262f..000000000 --- a/src/RoadRegistry.BackOffice/Configuration/RoadNetworkSnapshotStrategyOptions.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace RoadRegistry.BackOffice.Configuration; - -using RoadRegistry.BackOffice; - -public class RoadNetworkSnapshotStrategyOptions: IHasConfigurationKey -{ - public int EventCount { get; set; } = 50; - - public int GetLastAllowedStreamVersionToTakeSnapshot(int streamVersion /* Eg. 18499 */) - { - var streamDifference = streamVersion % EventCount; // Eg. 49 - var streamMaxVersion = streamVersion - streamDifference; // Eg. 18450 - - return streamMaxVersion; - } - - public string GetConfigurationKey() - { - return "SnapshotOptions"; - } -} diff --git a/src/RoadRegistry.BackOffice/Core/IRoadNetworks.cs b/src/RoadRegistry.BackOffice/Core/IRoadNetworks.cs index a6199d574..9b0910f30 100644 --- a/src/RoadRegistry.BackOffice/Core/IRoadNetworks.cs +++ b/src/RoadRegistry.BackOffice/Core/IRoadNetworks.cs @@ -8,9 +8,6 @@ public interface IRoadNetworks { Task Get(CancellationToken cancellationToken); Task Get(StreamName streamName, CancellationToken cancellationToken); - Task Get(bool restoreSnapshot, ProcessMessageHandler cancelMessageProcessing, CancellationToken cancellationToken); - Task<(RoadNetwork, int)> GetWithVersion(CancellationToken cancellationToken); Task<(RoadNetwork, int)> GetWithVersion(bool restoreSnapshot, ProcessMessageHandler cancelMessageProcessing, CancellationToken cancellationToken); - Task ForOutlinedRoadSegment(RoadSegmentId roadSegmentId, CancellationToken cancellationToken); } diff --git a/src/RoadRegistry.BackOffice/Core/RoadNetworks.cs b/src/RoadRegistry.BackOffice/Core/RoadNetworks.cs index e2623a8e6..033b83e18 100644 --- a/src/RoadRegistry.BackOffice/Core/RoadNetworks.cs +++ b/src/RoadRegistry.BackOffice/Core/RoadNetworks.cs @@ -64,27 +64,18 @@ public ProcessSnapshotContext(int? version) Version = version; } } - + public async Task Get(CancellationToken cancellationToken) { - var (roadNetwork, _) = await GetWithVersion(cancellationToken); + var (roadNetwork, _) = await GetWithVersion(true, null, cancellationToken); return roadNetwork; } + public async Task Get(StreamName streamName, CancellationToken cancellationToken) { var (roadNetwork, _) = await GetWithVersion(streamName, true, null, cancellationToken); return roadNetwork; } - public async Task Get(bool restoreSnapshot, ProcessMessageHandler cancelMessageProcessing, CancellationToken cancellationToken) - { - var (roadNetwork, _) = await GetWithVersion(restoreSnapshot, cancelMessageProcessing, cancellationToken); - return roadNetwork; - } - - public Task<(RoadNetwork, int)> GetWithVersion(CancellationToken cancellationToken) - { - return GetWithVersion(true, null, cancellationToken); - } public Task<(RoadNetwork, int)> GetWithVersion(bool restoreSnapshot, ProcessMessageHandler cancelMessageProcessing, CancellationToken cancellationToken) { @@ -124,7 +115,7 @@ public async Task ForOutlinedRoadSegment(RoadSegmentId roadSegmentI var roadNetwork = RoadNetwork.Factory(view.ToImmutable()); _map.Attach(new EventSourcedEntityMapEntry(roadNetwork, streamName, ExpectedVersion.Any)); - return (roadNetwork, snapshotContext.Version.Value); + return (roadNetwork, snapshotContext.Version!.Value); } private (RoadNetwork, int) EmptyRoadNetwork(StreamName streamName) @@ -137,7 +128,7 @@ public async Task ForOutlinedRoadSegment(RoadSegmentId roadSegmentI private async Task ProcessPages(StreamName streamName, IRoadNetworkView view, ProcessSnapshotContext snapshotContext, ReadStreamPage page, ProcessMessageHandler cancelMessageProcessing, CancellationToken cancellationToken) { view = await ProcessPage(view, snapshotContext, page, cancelMessageProcessing, cancellationToken); - + var sw = Stopwatch.StartNew(); while (!page.IsEnd && !snapshotContext.ProcessingCancelled) { @@ -160,7 +151,7 @@ private async Task ProcessPages(StreamName streamName, IRoadNe private async Task ProcessPage(IRoadNetworkView view, ProcessSnapshotContext snapshotContext, ReadStreamPage page, ProcessMessageHandler cancelMessageProcessing, CancellationToken cancellationToken) { var messages = new List(page.Messages.Length); - + foreach (var message in page.Messages) { cancellationToken.ThrowIfCancellationRequested(); @@ -204,12 +195,12 @@ await message.GetJsonData(cancellationToken), var sw = Stopwatch.StartNew(); int version; - + if (restoreSnapshot && streamName.SupportsSnapshot) { _logger.LogInformation("Read started for RoadNetwork snapshot"); var (snapshot, snapshotVersion) = await _snapshotReader.ReadSnapshotAsync(cancellationToken); - + _logger.LogInformation("Read finished for RoadNetwork snapshot version {SnapshotVersion} in {StopwatchElapsedMilliseconds}ms", snapshotVersion, sw.ElapsedMilliseconds); if (snapshot != null && snapshotVersion != ExpectedVersion.NoStream) diff --git a/src/RoadRegistry.BackOffice/Extensions/ServiceCollectionExtensions.cs b/src/RoadRegistry.BackOffice/Extensions/ServiceCollectionExtensions.cs index 6a9260605..1553c8a1c 100644 --- a/src/RoadRegistry.BackOffice/Extensions/ServiceCollectionExtensions.cs +++ b/src/RoadRegistry.BackOffice/Extensions/ServiceCollectionExtensions.cs @@ -1,8 +1,11 @@ namespace RoadRegistry.BackOffice.Extensions; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; using Amazon.SimpleEmailV2; using Be.Vlaanderen.Basisregisters.Aws.DistributedS3Cache; -using Be.Vlaanderen.Basisregisters.BlobStore.Sql; using Configuration; using Core; using FeatureCompare; @@ -11,16 +14,11 @@ namespace RoadRegistry.BackOffice.Extensions; using FeatureCompare.Validation; using FeatureToggle; using Framework; -using Microsoft.Data.SqlClient; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.IO; using NodaTime; -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; using Uploads; public static class ServiceCollectionExtensions @@ -111,7 +109,7 @@ public static IServiceCollection AddOrganizationCommandQueue(this IServiceCollec public static IServiceCollection AddEventEnricher(this IServiceCollection services) { return services - .AddSingleton(sp => EnrichEvent.WithTime(sp.GetRequiredService())); + .AddSingleton(sp => EnrichEvent.WithTime(sp.GetRequiredService())); } public static IServiceCollection AddRoadNetworkEventWriter(this IServiceCollection services) @@ -176,18 +174,6 @@ public static IServiceCollection RegisterOptions(this IServiceCollecti return services.AddSingleton(sp => sp.GetRequiredService().GetOptions(configurationSectionKey)); } - public static IServiceCollection AddRoadNetworkSnapshotStrategyOptions(this IServiceCollection services) - { - return services - .RegisterOptions(options => - { - if (options.EventCount <= 0) - { - throw new ConfigurationErrorsException($"{nameof(options.EventCount)} must be greater than zero"); - } - }); - } - public static IServiceCollection AddFeatureCompare(this IServiceCollection services) { return services diff --git a/src/RoadRegistry.Hosts/RoadRegistrySqsLambdaHandler.cs b/src/RoadRegistry.Hosts/RoadRegistrySqsLambdaHandler.cs index a4918cb5a..be3a8ad05 100644 --- a/src/RoadRegistry.Hosts/RoadRegistrySqsLambdaHandler.cs +++ b/src/RoadRegistry.Hosts/RoadRegistrySqsLambdaHandler.cs @@ -81,7 +81,6 @@ protected sealed override TicketError MapDomainException(DomainException excepti } } - return ticketError; } } diff --git a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Function.cs b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Function.cs index 9a0c4d688..9a3e8d70f 100644 --- a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Function.cs +++ b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Function.cs @@ -6,32 +6,22 @@ namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda; using Autofac; using BackOffice; -using BackOffice.Extensions; using Be.Vlaanderen.Basisregisters.EventHandling.Autofac; using Hosts; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; public class Function : RoadRegistryLambdaFunction { protected override string ApplicationName => "RoadRegistry.Snapshot.Handlers.Sqs.Lambda"; - public Function() : base(new[] { typeof(Sqs.DomainAssemblyMarker).Assembly }) + public Function() : base([typeof(SnapshotHandlersSqsAssemblyMarker).Assembly]) { } - protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) - { - services - .AddRoadNetworkSnapshotStrategyOptions() - ; - } - protected override void ConfigureContainer(HostBuilderContext context, ContainerBuilder builder) { builder - .RegisterModule(new EventHandlingModule(typeof(Sqs.DomainAssemblyMarker).Assembly, EventSerializerSettings)) - .RegisterModule() - ; + .RegisterModule(new EventHandlingModule(typeof(SnapshotHandlersSqsAssemblyMarker).Assembly, EventSerializerSettings)) + .RegisterModule(); } } diff --git a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/CreateRoadNetworkSnapshotSqsLambdaRequestHandler.cs b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/CreateRoadNetworkSnapshotSqsLambdaRequestHandler.cs index b15239130..d1cc7b763 100644 --- a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/CreateRoadNetworkSnapshotSqsLambdaRequestHandler.cs +++ b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/CreateRoadNetworkSnapshotSqsLambdaRequestHandler.cs @@ -3,7 +3,6 @@ namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Handlers; using System.Diagnostics; using BackOffice; using BackOffice.Abstractions.RoadNetworks; -using BackOffice.Configuration; using BackOffice.Core; using Be.Vlaanderen.Basisregisters.Sqs.Lambda.Infrastructure; using Hosts; @@ -16,7 +15,6 @@ public sealed class CreateRoadNetworkSnapshotSqsLambdaRequestHandler : SqsLambda { private readonly IRoadNetworkSnapshotReader _snapshotReader; private readonly IRoadNetworkSnapshotWriter _snapshotWriter; - private readonly RoadNetworkSnapshotStrategyOptions _snapshotStrategyOptions; private readonly Stopwatch _stopwatch; public CreateRoadNetworkSnapshotSqsLambdaRequestHandler( @@ -26,14 +24,12 @@ public CreateRoadNetworkSnapshotSqsLambdaRequestHandler( IRoadRegistryContext context, IRoadNetworkSnapshotReader snapshotReader, IRoadNetworkSnapshotWriter snapshotWriter, - RoadNetworkSnapshotStrategyOptions snapshotStrategyOptions, - ILogger logger) - : base(options, retryPolicy, ticketing, null, context, logger) + ILoggerFactory loggerFactory) + : base(options, retryPolicy, ticketing, context, loggerFactory.CreateLogger()) { _stopwatch = new Stopwatch(); _snapshotReader = snapshotReader; _snapshotWriter = snapshotWriter; - _snapshotStrategyOptions = snapshotStrategyOptions; } protected override async Task InnerHandle(CreateRoadNetworkSnapshotSqsLambdaRequest request, CancellationToken cancellationToken) @@ -42,38 +38,26 @@ protected override async Task InnerHandle(CreateRoadNetworkSnapshotSqsLa try { - var streamVersion = request.Request.StreamVersion; - var streamMaxVersion = _snapshotStrategyOptions.GetLastAllowedStreamVersionToTakeSnapshot(streamVersion); + var requestStreamVersion = request.Request.StreamVersion; + var snapshotStreamVersion = await _snapshotReader.ReadSnapshotVersionAsync(cancellationToken); - // Check if snapshot should be taken - if (streamVersion.Equals(streamMaxVersion)) + if (snapshotStreamVersion >= requestStreamVersion) { - var snapshotVersion = await _snapshotReader.ReadSnapshotVersionAsync(cancellationToken); - - // Check if current snapshot is already further that stream version - if (streamMaxVersion > 0 && snapshotVersion >= streamMaxVersion) - { - Logger.LogWarning("Create snapshot skipped for new message received from SQS with snapshot version {SnapshotVersion} and stream version {StreamVersion}", snapshotVersion, streamVersion); - } - else - { - var (roadnetwork, roadnetworkVersion) = await RoadRegistryContext.RoadNetworks.GetWithVersion(true, - (messageStreamVersion, _) => streamMaxVersion > 0 && messageStreamVersion > streamMaxVersion, cancellationToken); - var snapshot = roadnetwork.TakeSnapshot(); + Logger.LogWarning("Create snapshot skipped for new message received from SQS with snapshot version {SnapshotVersion} and stream version {StreamVersion}", snapshotStreamVersion, requestStreamVersion); + return new CreateRoadNetworkSnapshotResponse(null); + } - Logger.LogInformation("Create snapshot started for new message received from SQS with snapshot version {SnapshotVersion}", roadnetworkVersion); - await _snapshotWriter.WriteSnapshot(snapshot, roadnetworkVersion, cancellationToken); - Logger.LogInformation("Create snapshot completed for version {SnapshotVersion} in {TotalElapsedTimespan}", roadnetworkVersion, _stopwatch.Elapsed); + var (roadnetwork, roadnetworkVersion) = await RoadRegistryContext.RoadNetworks.GetWithVersion( + true, + cancelMessageProcessing: (_, _) => _stopwatch.Elapsed.Minutes >= 10, + cancellationToken); + var snapshot = roadnetwork.TakeSnapshot(); - return new CreateRoadNetworkSnapshotResponse(roadnetworkVersion); - } - } - else - { - Logger.LogInformation("Snapshot strategy determined that the strategy limit had not been reached"); - } + Logger.LogInformation("Create snapshot started for new message received from SQS with snapshot version {SnapshotVersion}", roadnetworkVersion); + await _snapshotWriter.WriteSnapshot(snapshot, roadnetworkVersion, cancellationToken); + Logger.LogInformation("Create snapshot completed for version {SnapshotVersion} in {TotalElapsedTimespan}", roadnetworkVersion, _stopwatch.Elapsed); - return new CreateRoadNetworkSnapshotResponse(null); + return new CreateRoadNetworkSnapshotResponse(roadnetworkVersion); } catch (Exception ex) { diff --git a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/SnapshotLambdaHealthCheckSqsLambdaRequestHandler.cs b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/SnapshotLambdaHealthCheckSqsLambdaRequestHandler.cs index 7ea33f061..b7bd19e8e 100644 --- a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/SnapshotLambdaHealthCheckSqsLambdaRequestHandler.cs +++ b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Handlers/SnapshotLambdaHealthCheckSqsLambdaRequestHandler.cs @@ -25,7 +25,7 @@ public SnapshotLambdaHealthCheckSqsLambdaRequestHandler( IRoadNetworkSnapshotReader snapshotReader, IRoadNetworkSnapshotWriter snapshotWriter, ILogger logger) - : base(options, retryPolicy, ticketing, null, context, logger) + : base(options, retryPolicy, ticketing, context, logger) { _snapshotReader = snapshotReader; _snapshotWriter = snapshotWriter; diff --git a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Infrastructure/SqsLambdaHandler.cs b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Infrastructure/SqsLambdaHandler.cs index 6ff00412e..dbf7f2fc9 100644 --- a/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Infrastructure/SqsLambdaHandler.cs +++ b/src/RoadRegistry.Snapshot.Handlers.Sqs.Lambda/Infrastructure/SqsLambdaHandler.cs @@ -16,10 +16,9 @@ protected SqsLambdaHandler( SqsLambdaHandlerOptions options, ICustomRetryPolicy retryPolicy, ITicketing ticketing, - IIdempotentCommandHandler idempotentCommandHandler, IRoadRegistryContext roadRegistryContext, ILogger logger) - : base(options, retryPolicy, ticketing, idempotentCommandHandler, roadRegistryContext, logger) + : base(options, retryPolicy, ticketing, null, roadRegistryContext, logger) { } diff --git a/src/RoadRegistry.Snapshot.Handlers.Sqs/DomainAssemblyMarker.cs b/src/RoadRegistry.Snapshot.Handlers.Sqs/DomainAssemblyMarker.cs deleted file mode 100644 index 126eb23ed..000000000 --- a/src/RoadRegistry.Snapshot.Handlers.Sqs/DomainAssemblyMarker.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs; - -public sealed class DomainAssemblyMarker -{ -} \ No newline at end of file diff --git a/src/RoadRegistry.Snapshot.Handlers.Sqs/SnapshotHandlersSqsAssemblyMarker.cs b/src/RoadRegistry.Snapshot.Handlers.Sqs/SnapshotHandlersSqsAssemblyMarker.cs new file mode 100644 index 000000000..7bd741093 --- /dev/null +++ b/src/RoadRegistry.Snapshot.Handlers.Sqs/SnapshotHandlersSqsAssemblyMarker.cs @@ -0,0 +1,4 @@ +namespace RoadRegistry.Snapshot.Handlers.Sqs; + +public sealed class SnapshotHandlersSqsAssemblyMarker +{ } diff --git a/src/RoadRegistry.Snapshot.Handlers/Handlers/RebuildRoadNetworkSnapshotRequestHandler.cs b/src/RoadRegistry.Snapshot.Handlers/Handlers/RebuildRoadNetworkSnapshotRequestHandler.cs index 61fe1e72c..c3cfdf351 100644 --- a/src/RoadRegistry.Snapshot.Handlers/Handlers/RebuildRoadNetworkSnapshotRequestHandler.cs +++ b/src/RoadRegistry.Snapshot.Handlers/Handlers/RebuildRoadNetworkSnapshotRequestHandler.cs @@ -1,29 +1,25 @@ namespace RoadRegistry.Snapshot.Handlers.Handlers; using System.Diagnostics; +using BackOffice; +using BackOffice.Abstractions.RoadNetworks; +using BackOffice.Core; using MediatR; using Microsoft.Extensions.Logging; -using RoadRegistry.BackOffice; -using RoadRegistry.BackOffice.Abstractions.RoadNetworks; -using RoadRegistry.BackOffice.Configuration; -using RoadRegistry.BackOffice.Core; public sealed class RebuildRoadNetworkSnapshotRequestHandler : IRequestHandler { private readonly IRoadRegistryContext _context; private readonly IRoadNetworkSnapshotWriter _snapshotWriter; - private readonly RoadNetworkSnapshotStrategyOptions _snapshotStrategyOptions; private readonly ILogger _logger; public RebuildRoadNetworkSnapshotRequestHandler( IRoadRegistryContext context, IRoadNetworkSnapshotWriter snapshotWriter, - RoadNetworkSnapshotStrategyOptions snapshotStrategyOptions, ILogger logger) { _context = context; _snapshotWriter = snapshotWriter; - _snapshotStrategyOptions = snapshotStrategyOptions; _logger = logger; } @@ -43,16 +39,11 @@ public async Task Handle(RebuildRoadNetworkS } var (roadNetwork, snapshotVersion) = await _context.RoadNetworks - .GetWithVersion(false, (messageStreamVersion, pageLastStreamVersion) => - { - if (request.MaxStreamVersion > 0 && messageStreamVersion > request.MaxStreamVersion) - { - return true; - } - - return messageStreamVersion > _snapshotStrategyOptions.GetLastAllowedStreamVersionToTakeSnapshot(pageLastStreamVersion); - } - , cancellationToken); + .GetWithVersion( + false, + cancelMessageProcessing: (messageStreamVersion, _) => + request.MaxStreamVersion > 0 && messageStreamVersion > request.MaxStreamVersion, + cancellationToken); var snapshot = roadNetwork.TakeSnapshot(); _logger.LogInformation("Create snapshot started with snapshot version {SnapshotVersion}", snapshotVersion); diff --git a/src/RoadRegistry.Snapshot.Handlers/RoadNetworkSnapshotEventModule.cs b/src/RoadRegistry.Snapshot.Handlers/RoadNetworkSnapshotEventModule.cs index f7de17ece..f4a58dbb0 100644 --- a/src/RoadRegistry.Snapshot.Handlers/RoadNetworkSnapshotEventModule.cs +++ b/src/RoadRegistry.Snapshot.Handlers/RoadNetworkSnapshotEventModule.cs @@ -36,10 +36,15 @@ ILoggerFactory loggerFactory For() .UseRoadRegistryContext(store, lifetimeScope, snapshotReader, loggerFactory, enricher) - .Handle(async (context, message, ct) => + .Handle(async (_, message, ct) => { logger.LogInformation("Event handler started for {EventName}", nameof(RoadNetworkChangesAccepted)); + if (message.StreamId != RoadNetworkStreamNameProvider.Default) + { + return; + } + await mediator.Send(new CreateRoadNetworkSnapshotSqsRequest { ProvenanceData = new RoadRegistryProvenanceData(), diff --git a/test/RoadRegistry.BackOffice.EventHost.Tests/RoadNetworkSnapshotEventModuleTests.cs b/test/RoadRegistry.BackOffice.EventHost.Tests/RoadNetworkSnapshotEventModuleTests.cs new file mode 100644 index 000000000..6df010b86 --- /dev/null +++ b/test/RoadRegistry.BackOffice.EventHost.Tests/RoadNetworkSnapshotEventModuleTests.cs @@ -0,0 +1,67 @@ +namespace RoadRegistry.BackOffice.EventHost.Tests; + +using AutoFixture; +using BackOffice.Framework; +using Core; +using MediatR; +using Messages; +using Moq; +using RoadRegistry.Tests.BackOffice.Scenarios; +using Snapshot.Handlers; +using Snapshot.Handlers.Sqs.RoadNetworks; +using Xunit.Abstractions; + +public class RoadNetworkSnapshotEventModuleTests : RoadNetworkTestBase +{ + private readonly Mock _mediator; + + public RoadNetworkSnapshotEventModuleTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + _mediator = new Mock(); + } + + [Fact] + public async Task WhenRoadNetworkChangesAccepted_ThenRequestSnapshot() + { + var streamId = RoadNetworkStreamNameProvider.Default; + var @event = new Event(TestData.ObjectProvider.Create()) + .WithStream(streamId, TestData.ObjectProvider.Create()); + + await DispatchEvent(@event); + + _mediator.Verify( + x => x.Send(It.IsAny(), It.IsAny()), + Times.Once); + } + + [Fact] + public async Task WhenOutlinedRoadNetworkChangesAccepted_ThenNone() + { + var streamId = TestData.ObjectProvider.Create(); + var @event = new Event(TestData.ObjectProvider.Create()) + .WithStream(streamId, TestData.ObjectProvider.Create()); + + await DispatchEvent(@event); + + _mediator.Verify( + x => x.Send(It.IsAny(), It.IsAny()), + Times.Never); + } + + private async Task DispatchEvent(Event @event) + { + var dispatcher = Dispatch.Using(Resolve.WhenEqualToMessage([ + new RoadNetworkSnapshotEventModule( + Store, + ScopedContainer, + _mediator.Object, + new FakeRoadNetworkSnapshotReader(), + new FakeRoadNetworkSnapshotWriter(), + Clock, + LoggerFactory + ) + ])); + await dispatcher(@event, CancellationToken.None); + } +} diff --git a/test/RoadRegistry.BackOffice.EventHost.Tests/Startup.cs b/test/RoadRegistry.BackOffice.EventHost.Tests/Startup.cs index 9f1e22f24..510068475 100644 --- a/test/RoadRegistry.BackOffice.EventHost.Tests/Startup.cs +++ b/test/RoadRegistry.BackOffice.EventHost.Tests/Startup.cs @@ -13,4 +13,4 @@ protected override void ConfigureContainer(ContainerBuilder builder) protected override void ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services) { } -} \ No newline at end of file +} diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/Framework/SqsLambdaHandlerFixture.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/Framework/SqsLambdaHandlerFixture.cs deleted file mode 100644 index d0afc2cdc..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/Framework/SqsLambdaHandlerFixture.cs +++ /dev/null @@ -1,196 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.Framework; - -using Autofac; -using BackOffice; -using BackOffice.Framework; -using BackOffice.Messages; -using Be.Vlaanderen.Basisregisters.CommandHandling.Idempotency; -using Be.Vlaanderen.Basisregisters.EventHandling; -using Be.Vlaanderen.Basisregisters.Sqs.Lambda.Infrastructure; -using Be.Vlaanderen.Basisregisters.Sqs.Lambda.Requests; -using Be.Vlaanderen.Basisregisters.Sqs.Requests; -using Be.Vlaanderen.Basisregisters.Sqs.Responses; -using Hosts; -using Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Moq; -using Newtonsoft.Json; -using NodaTime; -using RoadRegistry.Tests.BackOffice.Scenarios; -using SqlStreamStore; -using TicketingService.Abstractions; - -public abstract class SqsLambdaHandlerFixture : ApplicationFixture, IAsyncLifetime - where TSqsLambdaRequestHandler : SqsLambdaHandler - where TSqsLambdaRequest : SqsLambdaRequest - where TSqsRequest : SqsRequest -{ - private const string ConfigurationDetailUrl = "http://base/{0}"; - - private static readonly EventMapping Mapping = - new(EventMapping.DiscoverEventNamesInAssembly(typeof(RoadNetworkEvents).Assembly)); - - private static readonly JsonSerializerSettings Settings = - EventsJsonSerializerSettingsProvider.CreateSerializerSettings(); - - private static readonly StreamNameConverter StreamNameConverter = StreamNameConversions.PassThru; - protected readonly IConfiguration Configuration; - protected readonly ICustomRetryPolicy CustomRetryPolicy; - protected readonly IIdempotentCommandHandler IdempotentCommandHandler; - protected readonly ILifetimeScope LifetimeScope; - protected readonly ILoggerFactory LoggerFactory; - protected readonly SqsLambdaHandlerOptions Options; - protected readonly IRoadNetworkCommandQueue RoadNetworkCommandQueue; - protected readonly IRoadRegistryContext RoadRegistryContext; - protected readonly IStreamStore Store; - protected readonly RoadNetworkTestData TestData = new(); - - protected SqsLambdaHandlerFixture( - IConfiguration configuration, - ICustomRetryPolicy customRetryPolicy, - IStreamStore streamStore, - IRoadNetworkCommandQueue roadNetworkCommandQueue, - IClock clock, - SqsLambdaHandlerOptions options - ) - { - TestData.CopyCustomizationsTo(ObjectProvider); - - Configuration = new ConfigurationBuilder() - .AddConfiguration(configuration) - .AddInMemoryCollection(new Dictionary - { - { "DetailUrl", ConfigurationDetailUrl } - }) - .Build(); - - CustomRetryPolicy = customRetryPolicy; - Store = streamStore; - - var containerBuilder = new ContainerBuilder(); - containerBuilder - .Register(_ => new EventSourcedEntityMap()) - .AsSelf() - .SingleInstance(); - var container = containerBuilder.Build(); - LifetimeScope = container.BeginLifetimeScope(); - - RoadRegistryContext = new RoadRegistryContext( - LifetimeScope.Resolve(), - Store, new FakeRoadNetworkSnapshotReader(), - Settings, - Mapping, - EnrichEvent.WithTime(clock), - new NullLoggerFactory()); - RoadNetworkCommandQueue = roadNetworkCommandQueue; - Clock = clock; - Options = options; - - LoggerFactory = new LoggerFactory(); - - TicketingMock = MockTicketing(); - - var commandHandlerDispatcher = BuildCommandHandlerDispatcher(); - if (commandHandlerDispatcher is not null) - { - IdempotentCommandHandler = new RoadRegistryIdempotentCommandHandler(commandHandlerDispatcher); - } - - Exception = null; - } - - public IClock Clock { get; } - protected abstract TSqsLambdaRequestHandler SqsLambdaRequestHandler { get; } - protected abstract TSqsLambdaRequest SqsLambdaRequest { get; } - protected abstract TSqsRequest SqsRequest { get; } - protected Mock TicketingMock { get; } - public bool Result { get; private set; } - public Exception? Exception { get; private set; } - - public async Task InitializeAsync() - { - try - { - await SetupAsync(); - - await SqsLambdaRequestHandler.Handle(SqsLambdaRequest, CancellationToken.None); - - Result = await VerifyTicketAsync(); - } - catch (Exception ex) - { - Exception = ex; - } - } - - public Task DisposeAsync() - { - return Task.CompletedTask; - } - - protected virtual CommandHandlerDispatcher BuildCommandHandlerDispatcher() - { - return null; - } - - protected Task Given(StreamName streamName, params object[] events) - { - return Store.Given(Mapping, Settings, StreamNameConverter, streamName, events); - } - - protected virtual Mock MockTicketing() - { - return new Mock(); - } - - protected abstract Task SetupAsync(); - - protected bool VerifyThatTicketHasCompleted(string location, string eTag) - { - if (Exception is not null) - { - throw Exception; - } - - TicketingMock.Verify(x => - x.Complete( - It.IsAny(), - new TicketResult( - new ETagResponse(location, eTag) - ), - CancellationToken.None - ) - ); - - return true; - } - - protected async Task VerifyThatTicketHasCompleted(RoadSegmentId roadSegmentId) - { - var roadNetwork = await RoadRegistryContext.RoadNetworks.Get(CancellationToken.None); - var roadSegment = roadNetwork.FindRoadSegment(roadSegmentId); - - return VerifyThatTicketHasCompleted(string.Format(ConfigurationDetailUrl, roadSegmentId), roadSegment?.LastEventHash); - } - - protected bool VerifyThatTicketHasError(string code, string message) - { - if (Exception is not null) - { - throw Exception; - } - - TicketingMock.Verify(x => - x.Error(It.IsAny(), - new TicketError( - message, - code), - CancellationToken.None)); - - return true; - } - - protected abstract Task VerifyTicketAsync(); -} diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/Fixtures/SnapshotReaderFixture.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/Fixtures/SnapshotReaderFixture.cs deleted file mode 100644 index f3bd60c23..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/Fixtures/SnapshotReaderFixture.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.SnapshotReaderWriter.Fixtures; - -using BackOffice.Core; -using BackOffice.Messages; - -public class SnapshotReaderFixture : IAsyncLifetime -{ - private readonly IRoadNetworkSnapshotReader _reader; - - public SnapshotReaderFixture(IRoadNetworkSnapshotReader reader) - { - _reader = reader; - } - - public int? Version { get; private set; } - public RoadNetworkSnapshot Snapshot { get; private set; } - - public async Task InitializeAsync() - { - (Snapshot, Version) = await _reader.ReadSnapshotAsync(CancellationToken.None); - } - - public Task DisposeAsync() - { - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/Fixtures/SnapshotWriterFixture.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/Fixtures/SnapshotWriterFixture.cs deleted file mode 100644 index dbaf126c0..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/Fixtures/SnapshotWriterFixture.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.SnapshotReaderWriter.Fixtures; - -using BackOffice.Core; -using BackOffice.Messages; - -public class SnapshotWriterFixture : IAsyncLifetime -{ - private readonly IRoadNetworkSnapshotWriter _writer; - - public SnapshotWriterFixture(IRoadNetworkSnapshotWriter writer) - { - _writer = writer; - } - - public int Version { get; private set; } - public RoadNetworkSnapshot Snapshot { get; private set; } - - public async Task InitializeAsync() - { - var network = ImmutableRoadNetworkView.Empty; - - Snapshot = network.TakeSnapshot(); - Version = 0; - - await _writer.WriteSnapshot(Snapshot, Version, CancellationToken.None); - } - - public Task DisposeAsync() - { - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/SnapshotReaderTests.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/SnapshotReaderTests.cs deleted file mode 100644 index 4fca7017e..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/SnapshotReaderTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.SnapshotReaderWriter; - -using Fixtures; - -public class SnapshotReaderTests : IClassFixture -{ - private readonly SnapshotReaderFixture _fixture; - - public SnapshotReaderTests(SnapshotReaderFixture fixture) - { - _fixture = fixture; - } - - //[Fact] // Debugging - public void ItShouldSucceed() - { - Assert.NotEqual(0, _fixture.Version); - Assert.NotNull(_fixture.Snapshot); - Assert.NotEqual(default, _fixture.Snapshot); - } -} \ No newline at end of file diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/SnapshotWriterTests.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/SnapshotWriterTests.cs deleted file mode 100644 index e34f94c2c..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/SnapshotReaderWriter/SnapshotWriterTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.SnapshotReaderWriter; - -using Fixtures; - -public class SnapshotWriterTests : IClassFixture -{ - private readonly SnapshotWriterFixture _fixture; - - public SnapshotWriterTests(SnapshotWriterFixture fixture) - { - _fixture = fixture; - } - - //[Fact] // Debugging - public void ItShouldSucceed() - { - Assert.NotEqual(0, _fixture.Version); - Assert.NotNull(_fixture.Snapshot); - Assert.NotEqual(default, _fixture.Snapshot); - } -} \ No newline at end of file diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Abstractions/Fixtures/WhenCreateRoadNetworkSnapshotFixture.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Abstractions/Fixtures/WhenCreateRoadNetworkSnapshotFixture.cs deleted file mode 100644 index 9eb2200aa..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Abstractions/Fixtures/WhenCreateRoadNetworkSnapshotFixture.cs +++ /dev/null @@ -1,71 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.WhenCreateRoadNetworkSnapshot.Abstractions.Fixtures; - -using AutoFixture; -using BackOffice; -using BackOffice.Abstractions.RoadNetworks; -using BackOffice.Configuration; -using BackOffice.Core; -using Be.Vlaanderen.Basisregisters.GrAr.Provenance; -using Be.Vlaanderen.Basisregisters.Sqs.Lambda.Infrastructure; -using Framework; -using Handlers; -using Hosts; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Moq; -using NodaTime; -using Requests; -using SqlStreamStore; -using Sqs.RoadNetworks; - -public abstract class WhenCreateRoadNetworkSnapshotFixture : SqsLambdaHandlerFixture -{ - protected readonly Mock SnapshotReader; - protected readonly RoadNetworkSnapshotStrategyOptions SnapshotStrategyOptions; - protected readonly Mock SnapshotWriter; - - protected WhenCreateRoadNetworkSnapshotFixture( - IConfiguration configuration, - ICustomRetryPolicy customRetryPolicy, - IStreamStore streamStore, - IRoadNetworkCommandQueue roadNetworkCommandQueue, - IRoadNetworkSnapshotReader snapshotReader, - IRoadNetworkSnapshotWriter snapshotWriter, - IClock clock, - SqsLambdaHandlerOptions options) - : base(configuration, customRetryPolicy, streamStore, roadNetworkCommandQueue, clock, options) - { - Organisation = ObjectProvider.Create(); - SnapshotReader = CreateSnapshotReaderMock(snapshotReader); - SnapshotWriter = CreateSnapshotWriterMock(snapshotWriter); - SnapshotStrategyOptions = BuildSnapshotStrategyOptions(); - } - - protected Organisation Organisation { get; } - protected abstract CreateRoadNetworkSnapshotRequest Request { get; } - - protected override CreateRoadNetworkSnapshotSqsRequest SqsRequest => new() - { - Request = Request, - TicketId = Guid.NewGuid(), - Metadata = new Dictionary(), - ProvenanceData = ObjectProvider.Create() - }; - - protected override CreateRoadNetworkSnapshotSqsLambdaRequest SqsLambdaRequest => new(RoadNetworkStreamNameProvider.Default, SqsRequest); - - protected override CreateRoadNetworkSnapshotSqsLambdaRequestHandler SqsLambdaRequestHandler => new( - Options, - CustomRetryPolicy, - TicketingMock.Object, - RoadRegistryContext, - SnapshotReader.Object, - SnapshotWriter.Object, - SnapshotStrategyOptions, - LoggerFactory.CreateLogger() - ); - - protected abstract RoadNetworkSnapshotStrategyOptions BuildSnapshotStrategyOptions(); - protected abstract Mock CreateSnapshotReaderMock(IRoadNetworkSnapshotReader snapshotReader); - protected abstract Mock CreateSnapshotWriterMock(IRoadNetworkSnapshotWriter snapshotWriter); -} diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Abstractions/WhenCreateRoadNetworkSnapshot.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Abstractions/WhenCreateRoadNetworkSnapshot.cs deleted file mode 100644 index 27d6d0649..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Abstractions/WhenCreateRoadNetworkSnapshot.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.WhenCreateRoadNetworkSnapshot.Abstractions; - -using Fixtures; -using Xunit.Abstractions; - -public abstract class WhenCreateRoadNetworkSnapshot : IClassFixture - where TFixture : WhenCreateRoadNetworkSnapshotFixture -{ - protected TFixture Fixture; - protected ITestOutputHelper OutputHelper; - - protected WhenCreateRoadNetworkSnapshot(TFixture fixture, ITestOutputHelper testOutputHelper) - { - Fixture = fixture; - OutputHelper = testOutputHelper; - } -} \ No newline at end of file diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Fixtures/WhenCreateRoadNetworkSnapshotWithValidRequestFixture.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Fixtures/WhenCreateRoadNetworkSnapshotWithValidRequestFixture.cs deleted file mode 100644 index a45d98389..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/Fixtures/WhenCreateRoadNetworkSnapshotWithValidRequestFixture.cs +++ /dev/null @@ -1,119 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.WhenCreateRoadNetworkSnapshot.Fixtures; - -using Abstractions.Fixtures; -using BackOffice; -using BackOffice.Abstractions.RoadNetworks; -using BackOffice.Configuration; -using BackOffice.Core; -using BackOffice.Messages; -using Be.Vlaanderen.Basisregisters.Sqs.Lambda.Infrastructure; -using Hosts; -using Microsoft.Extensions.Configuration; -using Moq; -using NodaTime; -using NodaTime.Text; -using SqlStreamStore; -using AcceptedChange = BackOffice.Messages.AcceptedChange; - -public class WhenCreateRoadNetworkSnapshotWithValidRequestFixture : WhenCreateRoadNetworkSnapshotFixture -{ - public WhenCreateRoadNetworkSnapshotWithValidRequestFixture( - IConfiguration configuration, - ICustomRetryPolicy customRetryPolicy, - IStreamStore streamStore, - IRoadNetworkCommandQueue roadNetworkCommandQueue, - IRoadNetworkSnapshotReader snapshotReader, - IRoadNetworkSnapshotWriter snapshotWriter, - IClock clock, - SqsLambdaHandlerOptions options) - : base(configuration, customRetryPolicy, streamStore, roadNetworkCommandQueue, snapshotReader, snapshotWriter, clock, options) - { - } - - protected override CreateRoadNetworkSnapshotRequest Request => new() - { - StreamVersion = 3 - }; - - protected override RoadNetworkSnapshotStrategyOptions BuildSnapshotStrategyOptions() - { - return new RoadNetworkSnapshotStrategyOptions { EventCount = 3 }; - } - - protected override Mock CreateSnapshotReaderMock(IRoadNetworkSnapshotReader snapshotReader) - { - var mock = new Mock(); - mock.Setup(m => m.ReadSnapshotAsync(It.IsAny())) - .ReturnsAsync((new RoadNetworkSnapshot(), 0)); - return mock; - } - - protected override Mock CreateSnapshotWriterMock(IRoadNetworkSnapshotWriter snapshotWriter) - { - var mock = new Mock(); - return mock; - } - - protected override async Task SetupAsync() - { - await Given(Organizations.ToStreamName(TestData.ChangedByOrganization), new ImportedOrganization - { - Code = TestData.ChangedByOrganization, - Name = TestData.ChangedByOrganizationName, - When = InstantPattern.ExtendedIso.Format(Clock.GetCurrentInstant()) - }); - await Given(RoadNetworks.Stream, new RoadNetworkChangesAccepted - { - RequestId = TestData.RequestId, - Reason = TestData.ReasonForChange, - Operator = TestData.ChangedByOperator, - OrganizationId = TestData.ChangedByOrganization, - Organization = TestData.ChangedByOrganizationName, - Changes = new[] - { - new AcceptedChange - { - RoadNodeAdded = TestData.StartNode1Added - }, - new AcceptedChange - { - RoadNodeAdded = TestData.EndNode1Added - }, - new AcceptedChange - { - RoadSegmentAdded = TestData.Segment1Added - } - }, - When = InstantPattern.ExtendedIso.Format(Clock.GetCurrentInstant()) - }); - await Given(RoadNetworks.Stream, new RoadNetworkChangesAccepted - { - RequestId = TestData.RequestId, - Reason = TestData.ReasonForChange, - Operator = TestData.ChangedByOperator, - OrganizationId = TestData.ChangedByOrganization, - Organization = TestData.ChangedByOrganizationName, - Changes = new[] - { - new AcceptedChange - { - RoadNodeAdded = TestData.StartNode2Added - }, - new AcceptedChange - { - RoadNodeAdded = TestData.EndNode2Added - }, - new AcceptedChange - { - RoadSegmentAdded = TestData.Segment2Added - } - }, - When = InstantPattern.ExtendedIso.Format(Clock.GetCurrentInstant()) - }); - } - - protected override Task VerifyTicketAsync() - { - return Task.FromResult(true); - } -} \ No newline at end of file diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/GivenRoadNetwork.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/GivenRoadNetwork.cs new file mode 100644 index 000000000..cf12e6925 --- /dev/null +++ b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/GivenRoadNetwork.cs @@ -0,0 +1,115 @@ +namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.WhenCreateRoadNetworkSnapshot; + +using AutoFixture; +using BackOffice.Abstractions.RoadNetworks; +using BackOffice.Core; +using BackOffice.Messages; +using Be.Vlaanderen.Basisregisters.GrAr.Provenance; +using Handlers; +using Moq; +using NodaTime.Text; +using Requests; +using RoadRegistry.Tests.BackOffice; +using RoadRegistry.Tests.BackOffice.Scenarios; +using RoadRegistry.Tests.Framework; +using Sqs.RoadNetworks; +using Xunit.Abstractions; +using AcceptedChange = BackOffice.Messages.AcceptedChange; + +public class GivenRoadNetwork(ITestOutputHelper testOutputHelper) + : RoadNetworkTestBase(testOutputHelper) +{ + [Fact] + public async Task WhenRoadNetworkRequest_ThenSnapshotTaken() + { + // Arrange + await Given(Organizations.ToStreamName(TestData.ChangedByOrganization), + new ImportedOrganization + { + Code = TestData.ChangedByOrganization, + Name = TestData.ChangedByOrganizationName, + When = InstantPattern.ExtendedIso.Format(Clock.GetCurrentInstant()) + }); + await Given(RoadNetworkStreamNameProvider.Default, + new RoadNetworkChangesAccepted + { + RequestId = TestData.RequestId, + Reason = TestData.ReasonForChange, + Operator = TestData.ChangedByOperator, + OrganizationId = TestData.ChangedByOrganization, + Organization = TestData.ChangedByOrganizationName, + Changes = + [ + new AcceptedChange + { + RoadNodeAdded = TestData.StartNode1Added + }, + new AcceptedChange + { + RoadNodeAdded = TestData.EndNode1Added + }, + new AcceptedChange + { + RoadSegmentAdded = TestData.Segment1Added + } + ], + When = InstantPattern.ExtendedIso.Format(Clock.GetCurrentInstant()) + }, + new RoadNetworkChangesAccepted + { + RequestId = TestData.RequestId, + Reason = TestData.ReasonForChange, + Operator = TestData.ChangedByOperator, + OrganizationId = TestData.ChangedByOrganization, + Organization = TestData.ChangedByOrganizationName, + Changes = + [ + new AcceptedChange + { + RoadNodeAdded = TestData.StartNode2Added + }, + new AcceptedChange + { + RoadNodeAdded = TestData.EndNode2Added + }, + new AcceptedChange + { + RoadSegmentAdded = TestData.Segment2Added + } + ], + When = InstantPattern.ExtendedIso.Format(Clock.GetCurrentInstant()) + }); + + var snapshotReaderMock = new Mock(); + var snapshotWriterMock = new Mock(); + + // Act + var request = new CreateRoadNetworkSnapshotRequest + { + StreamVersion = 3 + }; + var handler = new CreateRoadNetworkSnapshotSqsLambdaRequestHandler( + new FakeSqsLambdaHandlerOptions(), + new FakeRetryPolicy(), + TicketingMock.Object, + RoadRegistryContext, + snapshotReaderMock.Object, + snapshotWriterMock.Object, + LoggerFactory + ); + await handler.Handle(new CreateRoadNetworkSnapshotSqsLambdaRequest( + RoadNetworkStreamNameProvider.Default, + new CreateRoadNetworkSnapshotSqsRequest + { + Request = request, + TicketId = Guid.NewGuid(), + Metadata = new Dictionary(), + ProvenanceData = ObjectProvider.Create() + }), + CancellationToken.None); + + // Assert + var expectedSnapshotStreamVersion = 1; + snapshotWriterMock.Verify(x => x.WriteSnapshot(It.IsAny(), expectedSnapshotStreamVersion, It.IsAny())); + } +} diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/WhenCreateRoadNetworkSnapshotWithValidRequest.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/WhenCreateRoadNetworkSnapshotWithValidRequest.cs deleted file mode 100644 index 8ff04adfd..000000000 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/RoadNetworks/WhenCreateRoadNetworkSnapshot/WhenCreateRoadNetworkSnapshotWithValidRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests.RoadNetworks.WhenCreateRoadNetworkSnapshot; - -using Abstractions; -using Fixtures; -using Xunit.Abstractions; - -public class WhenCreateRoadNetworkSnapshotWithValidRequest : WhenCreateRoadNetworkSnapshot -{ - public WhenCreateRoadNetworkSnapshotWithValidRequest(WhenCreateRoadNetworkSnapshotWithValidRequestFixture fixture, ITestOutputHelper outputHelper) : base(fixture, outputHelper) - { - } - - [Fact] - public void ItShouldSucceed() - { - if (Fixture.Exception is not null) - { - OutputHelper.WriteLine(Fixture.Exception.ToString()); - } - - Assert.True(Fixture.Result); - } -} \ No newline at end of file diff --git a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/Startup.cs b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/Startup.cs index 27d3fa2fb..69ed7d1ba 100644 --- a/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/Startup.cs +++ b/test/RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests/Startup.cs @@ -1,50 +1,5 @@ namespace RoadRegistry.Snapshot.Handlers.Sqs.Lambda.Tests; -using Autofac; -using BackOffice; -using BackOffice.Extensions; -using BackOffice.Framework; -using Be.Vlaanderen.Basisregisters.Sqs.Lambda.Infrastructure; -using Hosts; -using Hosts.Infrastructure.Modules; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using RoadRegistry.BackOffice.Core; -using RoadRegistry.Tests.BackOffice; -using RoadRegistry.Tests.Framework; -using SqlStreamStore; -using System.Reflection; -using MediatorModule = Sqs.MediatorModule; public class Startup : TestStartup { - protected override void ConfigureContainer(ContainerBuilder builder) - { - builder - .RegisterAssemblyTypes(typeof(MessageHandler).GetTypeInfo().Assembly) - .AsImplementedInterfaces(); - - builder.Register(c => new FakeSqsLambdaHandlerOptions()); - builder.Register(c => new RoadNetworkCommandQueue(c.Resolve(), new ApplicationMetadata(RoadRegistryApplication.Lambda))); - - builder - .RegisterModule() - .RegisterModule() - .RegisterModule() - .RegisterModule() - .RegisterModule() - ; - } - - protected override void ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services) - { - var configuration = hostBuilderContext.Configuration; - - services - .AddSingleton(_ => new EventSourcedEntityMap()) - .AddTransient(sp => new FakeRetryPolicy()) - .AddRoadRegistrySnapshot() - .AddSingleton() - .AddSingleton() - ; - } }