diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Extensions/ElasticSearchExtensions.cs b/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Extensions/ElasticSearchExtensions.cs index 47b7b4182..b27abae81 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Extensions/ElasticSearchExtensions.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Extensions/ElasticSearchExtensions.cs @@ -4,14 +4,15 @@ using Hosts.Configuration.ConfigurationBindings; using Nest; using Schema.Search; +using System.Text; public static class ElasticSearchExtensions { public static IServiceCollection AddElasticSearch( this IServiceCollection services, - ElasticSearchOptionsSection elasticSearchOptions) + ElasticSearchOptionsSection elasticSearchOptions, ILogger logger) { - var elasticClient = CreateElasticClient(elasticSearchOptions); + var elasticClient = CreateElasticClient(elasticSearchOptions, logger); EnsureIndexExists(elasticClient, elasticSearchOptions.Indices!.Verenigingen!, @@ -35,7 +36,7 @@ public static void EnsureIndexExists( elasticClient.Indices.CreateDuplicateDetectionIndex(duplicateDetectionIndexName); } - private static ElasticClient CreateElasticClient(ElasticSearchOptionsSection elasticSearchOptions) + public static ElasticClient CreateElasticClient(ElasticSearchOptionsSection elasticSearchOptions, ILogger logger) { var settings = new ConnectionSettings(new Uri(elasticSearchOptions.Uri!)) .BasicAuthentication( @@ -45,6 +46,23 @@ private static ElasticClient CreateElasticClient(ElasticSearchOptionsSection ela .MapVerenigingDocument(elasticSearchOptions.Indices!.Verenigingen!) .MapDuplicateDetectionDocument(elasticSearchOptions.Indices!.DuplicateDetection!); + if (elasticSearchOptions.EnableDevelopmentLogs) + settings = settings.DisableDirectStreaming() + .PrettyJson() + .OnRequestCompleted(apiCallDetails => + { + if (apiCallDetails.RequestBodyInBytes != null) + logger.LogDebug( + message: "{HttpMethod} {Uri} \n {RequestBody}", + apiCallDetails.HttpMethod, + apiCallDetails.Uri, + Encoding.UTF8.GetString(apiCallDetails.RequestBodyInBytes)); + + if (apiCallDetails.ResponseBodyInBytes != null) + logger.LogDebug(message: "Response: {ResponseBody}", + Encoding.UTF8.GetString(apiCallDetails.ResponseBodyInBytes)); + }); + var elasticClient = new ElasticClient(settings); return elasticClient; @@ -61,8 +79,11 @@ public static ConnectionSettings MapVerenigingDocument(this ConnectionSettings s public static ConnectionSettings MapDuplicateDetectionDocument(this ConnectionSettings settings, string indexName) { return settings.DefaultMappingFor( - typeof(DuplicateDetectionDocument), - selector: descriptor => descriptor.IndexName(indexName) - .IdProperty(nameof(DuplicateDetectionDocument.VCode))); + typeof(DuplicateDetectionDocument), + selector: descriptor => descriptor.IndexName(indexName) + .IdProperty(nameof(DuplicateDetectionDocument.VCode))) + .DefaultMappingFor(typeof(DuplicateDetectionUpdateDocument), + selector: descriptor => descriptor.IndexName(indexName) + .IdProperty(nameof(DuplicateDetectionDocument.VCode))); } } diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs b/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs index 6bb6e1bb5..23a6bf4e7 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs @@ -10,31 +10,15 @@ public static IServiceCollection ConfigureElasticSearch( this IServiceCollection services, ElasticSearchOptionsSection elasticSearchOptions) { - var elasticClient = CreateElasticClient(elasticSearchOptions); - - ElasticSearchExtensions.EnsureIndexExists(elasticClient, - elasticSearchOptions.Indices!.Verenigingen!, - elasticSearchOptions.Indices!.DuplicateDetection!); + var elasticClient = (IServiceProvider serviceProvider) + => ElasticSearchExtensions.CreateElasticClient(elasticSearchOptions, serviceProvider.GetRequiredService>()); services.AddSingleton(elasticSearchOptions); - services.AddSingleton(_ => elasticClient); - services.AddSingleton(_ => elasticClient); + services.AddSingleton(sp => elasticClient(sp)); - return services; - } + services.AddSingleton(sp => sp.GetRequiredService()); - private static ElasticClient CreateElasticClient(ElasticSearchOptionsSection elasticSearchOptions) - { - var settings = new ConnectionSettings(new Uri(elasticSearchOptions.Uri!)) - .BasicAuthentication( - elasticSearchOptions.Username, - elasticSearchOptions.Password) - .MapVerenigingDocument(elasticSearchOptions.Indices!.Verenigingen!) - .MapDuplicateDetectionDocument(elasticSearchOptions.Indices.DuplicateDetection!); - - var elasticClient = new ElasticClient(settings); - - return elasticClient; + return services; } } diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Program.cs b/src/AssociationRegistry.Admin.ProjectionHost/Program.cs index 5ce84ba28..a014b5e1d 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Program.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Program.cs @@ -3,6 +3,7 @@ namespace AssociationRegistry.Admin.ProjectionHost; using Asp.Versioning.ApplicationModels; using Extensions; using Infrastructure.ConfigurationBindings; +using Infrastructure.Extensions; using Infrastructure.Json; using Infrastructure.Metrics; using Infrastructure.Program; @@ -78,6 +79,10 @@ public static async Task Main(string[] args) var app = builder.Build(); + ElasticSearchExtensions.EnsureIndexExists(app.Services.GetRequiredService(), + elasticSearchOptions.Indices!.Verenigingen!, + elasticSearchOptions.Indices!.DuplicateDetection!); + app.AddProjectionEndpoints( app.Configuration.GetSection(RebuildConfigurationSection.SectionName).Get()!); diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs index ba550a941..bbd28e10b 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs @@ -49,7 +49,7 @@ public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.Data.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { Naam = message.Data.Naam, } @@ -58,7 +58,7 @@ public async Task Handle(EventEnvelope message) public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { VerenigingsTypeCode = Verenigingstype.Parse(message.Data.Rechtsvorm).Code, } @@ -67,7 +67,7 @@ public async Task Handle(EventEnvelope message) public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.Data.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { KorteNaam = message.Data.KorteNaam, } @@ -76,7 +76,7 @@ public async Task Handle(EventEnvelope message) public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { HoofdactiviteitVerenigingsloket = MapHoofdactiviteitVerenigingsloket(message.Data.HoofdactiviteitenVerenigingsloket), } @@ -94,7 +94,7 @@ public async Task Handle(EventEnvelope message) public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { IsGestopt = true, } @@ -103,7 +103,7 @@ public async Task Handle(EventEnvelope message) public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { IsGestopt = true, } @@ -112,7 +112,7 @@ public async Task Handle(EventEnvelope message) public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { IsVerwijderd = true, } @@ -142,7 +142,7 @@ private static DuplicateDetectionDocument.Locatie Map(Registratiedata.Locatie lo public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { Naam = message.Data.Naam, } @@ -151,7 +151,7 @@ public async Task Handle(EventEnvelope message) public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { KorteNaam = message.Data.KorteNaam, } @@ -187,7 +187,7 @@ public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { IsDubbel = true, } @@ -196,7 +196,7 @@ public async Task Handle(EventEnvelope mes public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { IsDubbel = false, } @@ -205,7 +205,7 @@ public async Task Handle(EventEnvelope message) => await _elasticRepository.UpdateAsync( message.VCode, - new DuplicateDetectionDocument + new DuplicateDetectionUpdateDocument { IsDubbel = false, } diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/IElasticRepository.cs b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/IElasticRepository.cs index 9cdddfa5b..8bf37f18a 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/IElasticRepository.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/IElasticRepository.cs @@ -23,5 +23,4 @@ Task IndexAsync(TDocument document) Task UpdateAdres(string id, int locatieId, string adresVoorstelling, string postcode, string gemeente) where TDocument : class; Task AppendCorresponderendeVCodes(string id, string vCodeDubbeleVereniging) where TDocument : class; Task RemoveCorresponderendeVCode(string id, string vCodeDubbeleVereniging) where TDocument : class; - } diff --git a/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs b/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs index a425d0fe5..f7f7d674b 100644 --- a/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs +++ b/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs @@ -1,5 +1,30 @@ namespace AssociationRegistry.Admin.Schema.Search; +// Use this for updates when properties are not nullable so it does not get overwritten on an updatepublic +public record DuplicateDetectionUpdateDocument +{ + public string VCode { get; set; } = null!; + public string Naam { get; set; } = null!; + public Locatie[] Locaties { get; set; } = null!; + public string VerenigingsTypeCode { get; set; } = null!; + public string KorteNaam { get; set; } = null!; + public string[] HoofdactiviteitVerenigingsloket { get; set; } = null!; + public bool? IsGestopt { get; set; } = null!; + public bool? IsVerwijderd { get; set; } = null!; + public bool? IsDubbel { get; set; } = null!; + + public record Locatie : ILocatie + { + public int LocatieId { get; init; } + public string Locatietype { get; init; } = null!; + public string? Naam { get; init; } + public string Adresvoorstelling { get; init; } = null!; + public bool? IsPrimair { get; init; } = null!; + public string Postcode { get; init; } = null!; + public string Gemeente { get; init; } = null!; + } +} + public record DuplicateDetectionDocument { public string VCode { get; set; } = null!; diff --git a/src/AssociationRegistry.Public.ProjectionHost/Extensions/ProjectionEndpointsExtensions.cs b/src/AssociationRegistry.Public.ProjectionHost/Extensions/ProjectionEndpointsExtensions.cs index 70e2dacb3..9a89545a1 100644 --- a/src/AssociationRegistry.Public.ProjectionHost/Extensions/ProjectionEndpointsExtensions.cs +++ b/src/AssociationRegistry.Public.ProjectionHost/Extensions/ProjectionEndpointsExtensions.cs @@ -1,13 +1,11 @@ namespace AssociationRegistry.Public.ProjectionHost.Extensions; +using Hosts.Configuration.ConfigurationBindings; using Infrastructure.ConfigurationBindings; using Infrastructure.Extensions; using Marten; -using Marten.Events.Daemon; using Nest; using Projections; -using Projections.Detail; -using Projections.Sequence; public static class ProjectionEndpointsExtensions { diff --git a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/ConfigurationBindings/ElasticSearchOptionsSection.cs b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/ConfigurationBindings/ElasticSearchOptionsSection.cs deleted file mode 100644 index d4d0853b0..000000000 --- a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/ConfigurationBindings/ElasticSearchOptionsSection.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace AssociationRegistry.Public.ProjectionHost.Infrastructure.ConfigurationBindings; - -public class ElasticSearchOptionsSection -{ - public string? Uri { get; set; } - public string? Username { get; set; } - public string? Password { get; set; } - public IndicesOptionsSection? Indices { get; set; } - - public class IndicesOptionsSection - { - public string? Verenigingen { get; set; } - } -} diff --git a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/ConfigHelpers.cs b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/ConfigHelpers.cs index 8426a4806..711faac06 100644 --- a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/ConfigHelpers.cs +++ b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/ConfigHelpers.cs @@ -1,6 +1,6 @@ namespace AssociationRegistry.Public.ProjectionHost.Infrastructure.Program; -using ConfigurationBindings; +using AssociationRegistry.Hosts.Configuration.ConfigurationBindings; using Framework; public static class ConfigHelpers diff --git a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplication/PrepareElasticSearch.cs b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplication/PrepareElasticSearch.cs index 2f73c032c..d86d86b1e 100644 --- a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplication/PrepareElasticSearch.cs +++ b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplication/PrepareElasticSearch.cs @@ -1,8 +1,8 @@ namespace AssociationRegistry.Public.ProjectionHost.Infrastructure.Program.WebApplication; -using ConfigurationBindings; using Extensions; using Hosts; +using Hosts.Configuration.ConfigurationBindings; using Nest; using Program = ProjectionHost.Program; using WebApplication = Microsoft.AspNetCore.Builder.WebApplication; diff --git a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigurationExtensions.cs b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigurationExtensions.cs index bd72935d4..ec01b30d5 100644 --- a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigurationExtensions.cs +++ b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigurationExtensions.cs @@ -1,12 +1,12 @@ namespace AssociationRegistry.Public.ProjectionHost.Infrastructure.Program.WebApplicationBuilder; -using ConfigurationBindings; +using Hosts.Configuration.ConfigurationBindings; public static class ConfigurationExtensions { public static PostgreSqlOptionsSection GetValidPostgreSqlOptionsOrThrow(this ConfigurationManager source) { - var postgreSqlOptions = source.GetSection(PostgreSqlOptionsSection.Name) + var postgreSqlOptions = source.GetSection(PostgreSqlOptionsSection.SectionName) .Get(); ConfigHelpers.ThrowIfInvalidPostgreSqlOptions(postgreSqlOptions); diff --git a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs index 585ef9b39..f583cde6f 100644 --- a/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs +++ b/src/AssociationRegistry.Public.ProjectionHost/Infrastructure/Program/WebApplicationBuilder/ConfigureElasticSearchExtensions.cs @@ -1,6 +1,6 @@ namespace AssociationRegistry.Public.ProjectionHost.Infrastructure.Program.WebApplicationBuilder; -using ConfigurationBindings; +using Hosts.Configuration.ConfigurationBindings; using Nest; using Schema; @@ -20,7 +20,7 @@ public static IServiceCollection ConfigureElasticSearch( return services; } - private static ElasticClient CreateElasticClient(ElasticSearchOptionsSection elasticSearchOptions) + public static ElasticClient CreateElasticClient(ElasticSearchOptionsSection elasticSearchOptions) { var settings = new ConnectionSettings(new Uri(elasticSearchOptions.Uri!)) .BasicAuthentication( diff --git a/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommand.cs b/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommand.cs index 716b2f209..b63556021 100644 --- a/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommand.cs +++ b/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommand.cs @@ -1,5 +1,5 @@ namespace AssociationRegistry.DecentraalBeheer.Dubbelbeheer.AanvaardDubbel; -using AssociationRegistry.Vereniging; +using Vereniging; public record AanvaardDubbeleVerenigingCommand(VCode VCode, VCode VCodeDubbeleVereniging); diff --git a/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommandHandler.cs b/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommandHandler.cs index 2b2990e73..7b60799b3 100644 --- a/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommandHandler.cs +++ b/src/AssociationRegistry/DecentraalBeheer/Dubbelbeheer/AanvaardDubbel/AanvaardDubbeleVerenigingCommandHandler.cs @@ -1,9 +1,10 @@ namespace AssociationRegistry.DecentraalBeheer.Dubbelbeheer.AanvaardDubbel; -using AssociationRegistry.EventStore; -using AssociationRegistry.Framework; -using AssociationRegistry.Messages; -using AssociationRegistry.Vereniging; +using EventStore; +using Framework; +using Messages; +using Vereniging; +using Be.Vlaanderen.Basisregisters.AggregateSource; using NodaTime; using Wolverine; @@ -26,7 +27,11 @@ await repository.Save( Guid.NewGuid()), cancellationToken); } - catch (Exception) + catch (AggregateNotFoundException) + { + await bus.SendAsync(new VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage(command.VCodeDubbeleVereniging, command.VCode)); + } + catch (DomainException) { await bus.SendAsync(new VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage(command.VCodeDubbeleVereniging, command.VCode)); } diff --git a/src/AssociationRegistry/Vereniging/VerenigingStatus.cs b/src/AssociationRegistry/Vereniging/VerenigingStatus.cs index 8a86cd66e..5bcbf29ef 100644 --- a/src/AssociationRegistry/Vereniging/VerenigingStatus.cs +++ b/src/AssociationRegistry/Vereniging/VerenigingStatus.cs @@ -17,7 +17,7 @@ public record StatusDubbel(VCode VCodeAuthentiekeVereniging, VerenigingStatus Vo public static VerenigingStatus Actief => new StatusActief(); public static VerenigingStatus Gestopt => new StatusGestopt(); - public VerenigingStatus ParseVorigeStatus(string vorigeStatus) + public static VerenigingStatus ParseVorigeStatus(string vorigeStatus) { switch (vorigeStatus) { diff --git a/test/AssociationRegistry.Test.E2E/When_Aanvaard_Dubbel_Van_Handler_Fails/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs b/test/AssociationRegistry.Test.E2E/When_Aanvaard_Dubbel_Van_Handler_Fails/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs new file mode 100644 index 000000000..63b0d20d5 --- /dev/null +++ b/test/AssociationRegistry.Test.E2E/When_Aanvaard_Dubbel_Van_Handler_Fails/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs @@ -0,0 +1,141 @@ +namespace AssociationRegistry.Test.E2E.When_Aanvaard_Dubbel_Van_Handler_Fails; + +using Events; +using EventStore; +using AssociationRegistry.Framework; +using Messages; +using AssociationRegistry.Test.Common.AutoFixture; +using Framework.ApiSetup; +using Vereniging; +using AutoFixture; +using FluentAssertions; +using Marten; +using Microsoft.Extensions.DependencyInjection; +using NodaTime; +using Wolverine; +using Wolverine.Persistence.Durability; +using Xunit; +using Xunit.Abstractions; + +[Collection(FullBlownApiCollection.Name)] +public class Given_Incorrect_VCode_In_The_Message +{ + private readonly FullBlownApiSetup _setup; + private readonly ITestOutputHelper _testOutputHelper; + private readonly Fixture _autoFixture; + + public Given_Incorrect_VCode_In_The_Message(FullBlownApiSetup setup, ITestOutputHelper testOutputHelper) + { + _autoFixture = new Fixture().CustomizeAdminApi(); + + _setup = setup; + _testOutputHelper = testOutputHelper; + } + + /// + /// AanvaardDubbeleVerenigingMessage (onbestaande vCode) -> AanvaardDubbeleVerenigingMessagehandler + /// AanvaardDubbeleVerenigingMessageHandler -> throws domain exception -> send message VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage + /// VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage (onbestaande vCode) -> VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessageHandler + /// VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessageHandler -> throws exception -> Message comes on dlq + /// + [Fact] + public async Task Then_VerwerkWeigeringDubbelDoorAuthentiekeVerenigingHandler_Puts_A_Message_On_The_Dlq() + { + var bus = _setup.AdminApiHost.Services.GetRequiredService(); + var messageStore = _setup.AdminApiHost.Services.GetRequiredService(); + + await PurgeDeadLetters(messageStore, typeof(VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage).FullName); + + var aanvaardDubbeleVerenigingMessage = _autoFixture.Create() + with + { + VCode = _autoFixture.Create(), + VCodeDubbeleVereniging = _autoFixture.Create(), + }; + + await bus.SendAsync(aanvaardDubbeleVerenigingMessage); + + var messages = await WaitForMessageInDlq(messageStore); + + var message = messages.ShouldHaveMessageOfType(); + message.Envelope.MessageType.Should().Be(typeof(VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage).FullName); + } + + /// + /// AanvaardDubbeleVerenigingMessage (onbestaande vCode) -> AanvaardDubbeleVerenigingMessagehandler + /// AanvaardDubbeleVerenigingMessageHandler -> throws uncaught exception -> puts AanvaardDubbeleVerenigingMessage on DLQ + /// + [Fact (Skip = "This breaks other tests.")] + public async Task Then_The_Dlq_Receives_AanvaardDubbeleVerenigingMessage() + { + var bus = _setup.AdminApiHost.Services.GetRequiredService(); + var messageStore = _setup.AdminApiHost.Services.GetRequiredService(); + var eventstore = _setup.AdminApiHost.Services.GetRequiredService(); + + await PurgeDeadLetters(messageStore, typeof(VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage).FullName); + + var aanvaardDubbeleVerenigingMessage = await StoreImpossibleEventThatWillCrashTheEventStore(eventstore); + + await bus.SendAsync(aanvaardDubbeleVerenigingMessage); + + var messages = await WaitForMessageInDlq(messageStore); + + var message = messages.ShouldHaveMessageOfType(); + message.Envelope.MessageType.Should().Be(typeof(AanvaardDubbeleVerenigingMessage).FullName); + + var session = _setup.AdminApiHost.Services.GetRequiredService(); + session.Events.ArchiveStream(aanvaardDubbeleVerenigingMessage.VCode); + } + + private async Task StoreImpossibleEventThatWillCrashTheEventStore(IEventStore eventstore) + { + var aanvaardDubbeleVerenigingMessage = _autoFixture.Create() + with + { + VCode = _autoFixture.Create(), + VCodeDubbeleVereniging = _autoFixture.Create(), + }; + + await eventstore.Save(aanvaardDubbeleVerenigingMessage.VCode, new CommandMetadata("test", new Instant(), Guid.NewGuid(), null), + CancellationToken.None, new VerenigingWerdGestopt(new DateOnly())); + + return aanvaardDubbeleVerenigingMessage; + } + + private async Task?> WaitForMessageInDlq(IMessageStore messageStore) + { + var maxRetries = 120; + var tries = 0; + IReadOnlyList messages = null; + while (tries < maxRetries) + { + tries++; + + var envelopesFound = await messageStore.DeadLetters.QueryDeadLetterEnvelopesAsync(new DeadLetterEnvelopeQueryParameters()); + messages = envelopesFound.DeadLetterEnvelopes.Where(x => x.MessageType == typeof(TMessage).FullName).ToArray(); + + var deadLetterEnvelopes = envelopesFound.DeadLetterEnvelopes; + deadLetterEnvelopes.ToList().ForEach(x => _testOutputHelper.WriteLine(x.MessageType)); + + if (messages.Any()) + { + break; + } + + _testOutputHelper.WriteLine($"Attempt {tries}"); + await Task.Delay(500); + } + + return messages; + } + + private static async Task PurgeDeadLetters(IMessageStore messageStore, string? messageType) + { + var deadLetters = await messageStore.DeadLetters.QueryDeadLetterEnvelopesAsync(new DeadLetterEnvelopeQueryParameters() + { + MessageType = messageType, + }); + + await messageStore.DeadLetters.DeleteDeadLetterEnvelopesAsync(deadLetters.DeadLetterEnvelopes.Select(x => x.Id).ToArray()); + } +} diff --git a/test/AssociationRegistry.Test.E2E/When_Markeer_Als_Dubbel_Van_Fails/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs b/test/AssociationRegistry.Test.E2E/When_Markeer_Als_Dubbel_Van_Fails/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs deleted file mode 100644 index 0598aaba7..000000000 --- a/test/AssociationRegistry.Test.E2E/When_Markeer_Als_Dubbel_Van_Fails/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs +++ /dev/null @@ -1,83 +0,0 @@ -namespace AssociationRegistry.Test.E2E.When_Markeer_Als_Dubbel_Van_Fails; - -using AutoFixture; -using Common.AutoFixture; -using FluentAssertions; -using Framework.ApiSetup; -using Messages; -using Microsoft.Extensions.DependencyInjection; -using Vereniging; -using Vereniging.Exceptions; -using Wolverine; -using Wolverine.Persistence.Durability; -using Xunit; -using Xunit.Abstractions; - -[Collection(FullBlownApiCollection.Name)] -public class When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue -{ - private readonly FullBlownApiSetup _setup; - private readonly ITestOutputHelper _testOutputHelper; - private readonly Fixture _autoFixture; - - public When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue(FullBlownApiSetup setup, ITestOutputHelper testOutputHelper) - { - _autoFixture = new Fixture().CustomizeAdminApi(); - - _setup = setup; - _testOutputHelper = testOutputHelper; - } - - [Fact] - public async Task Then_The_Dlq_Receives_The_Message() - { - var bus = _setup.AdminApiHost.Services.GetRequiredService(); - var messageStore = _setup.AdminApiHost.Services.GetRequiredService(); - - await PurgeDeadLetters(messageStore, typeof(VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage).FullName); - - var aanvaardDubbeleVerenigingMessage = _autoFixture.Create() - with - { - VCode = _autoFixture.Create(), - VCodeDubbeleVereniging = _autoFixture.Create(), - }; - - await bus.SendAsync(aanvaardDubbeleVerenigingMessage); - - var maxRetries = 120; - var tries = 0; - IReadOnlyList messages = null; - while (tries < maxRetries) - { - tries++; - - var envelopesFound = await messageStore.DeadLetters.QueryDeadLetterEnvelopesAsync(new DeadLetterEnvelopeQueryParameters()); - messages = envelopesFound.DeadLetterEnvelopes.Where(x => x.MessageType == typeof(VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage).FullName).ToArray(); - - var deadLetterEnvelopes = envelopesFound.DeadLetterEnvelopes; - deadLetterEnvelopes.ToList().ForEach(x => _testOutputHelper.WriteLine(x.MessageType)); - - if (messages.Any()) - { - break; - } - - _testOutputHelper.WriteLine($"Attempt {tries}"); - await Task.Delay(500); - } - - var message = messages.ShouldHaveMessageOfType(); - message.Envelope.MessageType.Should().Be(typeof(VerwerkWeigeringDubbelDoorAuthentiekeVerenigingMessage).FullName); - } - - private static async Task PurgeDeadLetters(IMessageStore messageStore, string? messageType) - { - var deadLetters = await messageStore.DeadLetters.QueryDeadLetterEnvelopesAsync(new DeadLetterEnvelopeQueryParameters() - { - MessageType = messageType, - }); - - await messageStore.DeadLetters.DeleteDeadLetterEnvelopesAsync(deadLetters.DeadLetterEnvelopes.Select(x => x.Id).ToArray()); - } -} diff --git a/test/AssociationRegistry.Test.E2E/When_Messages_Are_Queued/Via_Postgres/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs b/test/AssociationRegistry.Test.E2E/When_Messages_Are_Queued/Via_Postgres/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs index bde150fdb..1500fc7de 100644 --- a/test/AssociationRegistry.Test.E2E/When_Messages_Are_Queued/Via_Postgres/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs +++ b/test/AssociationRegistry.Test.E2E/When_Messages_Are_Queued/Via_Postgres/When_Sending_An_Incorrect_Message_On_The_AanvaardDubbeleVereniging_Queue.cs @@ -38,9 +38,6 @@ public async Task Then_The_Dlq_Receives_The_Message() await bus.SendAsync(aanvaardDubbeleVerenigingMessage); - - - var maxRetries = 5; var tries = 0; IReadOnlyList messages = null; diff --git a/test/AssociationRegistry.Test.E2E/appsettings.e2e.publicproj.json b/test/AssociationRegistry.Test.E2E/appsettings.e2e.publicproj.json index 1fc01b9da..e7555a77b 100644 --- a/test/AssociationRegistry.Test.E2E/appsettings.e2e.publicproj.json +++ b/test/AssociationRegistry.Test.E2E/appsettings.e2e.publicproj.json @@ -1,5 +1,6 @@ { "ElasticClientOptions": { + "EnableDevelopmentLogs": true, "Uri": "http://127.0.0.1:9200", "Username": "elastic", "Password": "local_development", diff --git a/test/AssociationRegistry.Test.Projections/Beheer/Detail/Dubbels/Given_MarkeringDubbeleVerengingWerdGecorrigeerd.cs b/test/AssociationRegistry.Test.Projections/Beheer/Detail/Dubbels/Given_MarkeringDubbeleVerengingWerdGecorrigeerd.cs index adfb17a75..c01f64c6a 100644 --- a/test/AssociationRegistry.Test.Projections/Beheer/Detail/Dubbels/Given_MarkeringDubbeleVerengingWerdGecorrigeerd.cs +++ b/test/AssociationRegistry.Test.Projections/Beheer/Detail/Dubbels/Given_MarkeringDubbeleVerengingWerdGecorrigeerd.cs @@ -1,7 +1,5 @@ namespace AssociationRegistry.Test.Projections.Beheer.Detail.Dubbels; -using Admin.Schema.Constants; - [Collection(nameof(ProjectionContext))] public class Given_MarkeringDubbeleVerengingWerdGecorrigeerd(BeheerDetailScenarioFixture fixture) : BeheerDetailScenarioClassFixture diff --git a/test/AssociationRegistry.Test.Projections/Beheer/DuplicateDetection/Dubbels/Given_MarkeringDubbeleVerengingWerdGecorrigeerdVanEenGestopteVereniging.cs b/test/AssociationRegistry.Test.Projections/Beheer/DuplicateDetection/Dubbels/Given_MarkeringDubbeleVerengingWerdGecorrigeerdVanEenGestopteVereniging.cs new file mode 100644 index 000000000..6cf98b0e1 --- /dev/null +++ b/test/AssociationRegistry.Test.Projections/Beheer/DuplicateDetection/Dubbels/Given_MarkeringDubbeleVerengingWerdGecorrigeerdVanEenGestopteVereniging.cs @@ -0,0 +1,10 @@ +namespace AssociationRegistry.Test.Projections.Beheer.DuplicateDetection.Dubbels; + +[Collection(nameof(ProjectionContext))] +public class MarkeringDubbeleVerengingWerdGecorrigeerdVanEenGestopteVereniging(DuplicateDetectionScenarioFixture fixture) + : DuplicateDetectionClassFixture +{ + [Fact] + public void Status_Is_Gestopt() + => fixture.Result.IsGestopt.Should().BeTrue(); +} diff --git a/test/AssociationRegistry.Test.Projections/Framework/ProjectionContext.cs b/test/AssociationRegistry.Test.Projections/Framework/ProjectionContext.cs index c11ad2d4d..a55b5a147 100644 --- a/test/AssociationRegistry.Test.Projections/Framework/ProjectionContext.cs +++ b/test/AssociationRegistry.Test.Projections/Framework/ProjectionContext.cs @@ -21,7 +21,9 @@ public class ProjectionContext : IProjectionContext, IAsyncLifetime public IDocumentStore PublicStore { get; set; } public IDocumentStore AcmStore { get; set; } public IElasticClient AdminElasticClient { get; set; } + public IElasticClient AdminProjectionElasticClient { get; set; } public IElasticClient PublicElasticClient { get; set; } + public IElasticClient PublicProjectionElasticClient { get; set; } public ProjectionContext() { @@ -37,13 +39,17 @@ public async Task InitializeAsync() Admin.Api.Infrastructure.Extensions.ElasticSearchExtensions.CreateElasticClient( Configuration.GetElasticSearchOptionsSection(), NullLogger.Instance); + AdminProjectionElasticClient = + Admin.ProjectionHost.Infrastructure.Extensions.ElasticSearchExtensions.CreateElasticClient( + Configuration.GetElasticSearchOptionsSection(), NullLogger.Instance); + var adminStore = DocumentStore.For( opts => { ConfigureMartenExtensions.ConfigureStoreOptions(opts, NullLogger.Instance, NullLogger.Instance, - new ElasticRepository(AdminElasticClient), + new ElasticRepository(AdminProjectionElasticClient), true, NullLogger.Instance, new PostgreSqlOptionsSection() @@ -64,12 +70,16 @@ public async Task InitializeAsync() Public.Api.Infrastructure.Extensions.ElasticSearchExtensions.CreateElasticClient( Configuration.GetElasticSearchOptionsSection(), NullLogger.Instance); + PublicProjectionElasticClient = + Public.ProjectionHost.Infrastructure.Program.WebApplicationBuilder.ConfigureElasticSearchExtensions.CreateElasticClient( + Configuration.GetElasticSearchOptionsSection()); + var publicStore = DocumentStore.For( opts => { Public.ProjectionHost.Infrastructure.Program.WebApplicationBuilder.ConfigureMartenExtensions.ConfigureStoreOptions( opts, - new AssociationRegistry.Public.ProjectionHost.Projections.Search.ElasticRepository(PublicElasticClient), + new AssociationRegistry.Public.ProjectionHost.Projections.Search.ElasticRepository(PublicProjectionElasticClient), NullLogger.Instance, new PostgreSqlOptionsSection() { diff --git a/test/AssociationRegistry.Test.Projections/Scenario/MarkeringDubbeleVerengingWerdGecorrigeerdMetVorigeStatusGestoptScenario.cs b/test/AssociationRegistry.Test.Projections/Scenario/MarkeringDubbeleVerengingWerdGecorrigeerdMetVorigeStatusGestoptScenario.cs new file mode 100644 index 000000000..062eea503 --- /dev/null +++ b/test/AssociationRegistry.Test.Projections/Scenario/MarkeringDubbeleVerengingWerdGecorrigeerdMetVorigeStatusGestoptScenario.cs @@ -0,0 +1,59 @@ +namespace AssociationRegistry.Test.Projections.Scenario; + +using AutoFixture; +using Events; + +public class MarkeringDubbeleVerengingWerdGecorrigeerdMetVorigeStatusGestoptScenario : InszScenarioBase +{ + public FeitelijkeVerenigingWerdGeregistreerd DubbeleVerenigingWerdGeregistreerd { get; } + public FeitelijkeVerenigingWerdGeregistreerd AuthentiekeVerenigingWerdGeregistreerd { get; } + public VerenigingWerdGemarkeerdAlsDubbelVan VerenigingWerdGemarkeerdAlsDubbelVan { get; set; } + public VerenigingAanvaarddeDubbeleVereniging VerenigingAanvaarddeDubbeleVereniging { get; set; } + public VerenigingWerdGestopt VerenigingWerdGestopt { get; set; } + public MarkeringDubbeleVerengingWerdGecorrigeerd MarkeringDubbeleVerengingWerdGecorrigeerd { get; set; } + + private string _insz { get; } + public MarkeringDubbeleVerengingWerdGecorrigeerdMetVorigeStatusGestoptScenario() + { + + DubbeleVerenigingWerdGeregistreerd = AutoFixture.Create(); + + AuthentiekeVerenigingWerdGeregistreerd = AutoFixture.Create() + with + { + Vertegenwoordigers = DubbeleVerenigingWerdGeregistreerd.Vertegenwoordigers, + }; + + _insz = AuthentiekeVerenigingWerdGeregistreerd.Vertegenwoordigers[0].Insz; + + VerenigingWerdGemarkeerdAlsDubbelVan = AutoFixture.Create() with + { + VCode = DubbeleVerenigingWerdGeregistreerd.VCode, + VCodeAuthentiekeVereniging = AuthentiekeVerenigingWerdGeregistreerd.VCode + }; + + VerenigingAanvaarddeDubbeleVereniging = AutoFixture.Create() with + { + VCode = AuthentiekeVerenigingWerdGeregistreerd.VCode, + VCodeDubbeleVereniging = DubbeleVerenigingWerdGeregistreerd.VCode, + }; + + VerenigingWerdGestopt = AutoFixture.Create(); + + MarkeringDubbeleVerengingWerdGecorrigeerd = AutoFixture.Create() with + { + VCode = DubbeleVerenigingWerdGeregistreerd.VCode, + VCodeAuthentiekeVereniging = AuthentiekeVerenigingWerdGeregistreerd.VCode, + }; + } + + public override string VCode => DubbeleVerenigingWerdGeregistreerd.VCode; + + public override EventsPerVCode[] Events => + [ + new(VCode, DubbeleVerenigingWerdGeregistreerd, VerenigingWerdGemarkeerdAlsDubbelVan, VerenigingWerdGestopt, MarkeringDubbeleVerengingWerdGecorrigeerd), + new(AuthentiekeVerenigingWerdGeregistreerd.VCode, AuthentiekeVerenigingWerdGeregistreerd, VerenigingAanvaarddeDubbeleVereniging), + ]; + + public override string Insz => _insz; +} diff --git a/test/AssociationRegistry.Test/Dubbelbeheer/When_AanvaardDubbeleVereniging/Given_VCode_And_VCodeDubbeleVereniging_Are_The_Same.cs b/test/AssociationRegistry.Test/Dubbelbeheer/When_AanvaardDubbeleVereniging/Given_VCode_And_VCodeDubbeleVereniging_Are_The_Same.cs index 5716d529b..bc68b254f 100644 --- a/test/AssociationRegistry.Test/Dubbelbeheer/When_AanvaardDubbeleVereniging/Given_VCode_And_VCodeDubbeleVereniging_Are_The_Same.cs +++ b/test/AssociationRegistry.Test/Dubbelbeheer/When_AanvaardDubbeleVereniging/Given_VCode_And_VCodeDubbeleVereniging_Are_The_Same.cs @@ -1,15 +1,14 @@ namespace AssociationRegistry.Test.Dubbelbeheer.When_AanvaardDubbeleVereniging; -using AssociationRegistry.Messages; -using AssociationRegistry.Resources; -using AssociationRegistry.Test.Common.AutoFixture; -using AssociationRegistry.Test.Common.Framework; -using AssociationRegistry.Test.Common.Scenarios.CommandHandling; -using AssociationRegistry.Vereniging.Exceptions; using AutoFixture; +using Common.AutoFixture; +using Common.Framework; +using Common.Scenarios.CommandHandling; using DecentraalBeheer.Dubbelbeheer.AanvaardDubbel; using FluentAssertions; using Moq; +using Resources; +using Vereniging.Exceptions; using Wolverine; using Xunit; @@ -30,11 +29,8 @@ public async Task Then_Throws_InvalidOperationVerenigingKanGeenDubbelWordenVanZi }; var sut = new AanvaardDubbeleVerenigingCommandHandler(repositoryMock, messageBus.Object); - await sut.Handle(command, CancellationToken.None); + var exception = await Assert.ThrowsAsync(async () => await sut.Handle(command, CancellationToken.None)) ; - messageBus.Verify(x => x.SendAsync( - It.Is(y => y.VCode == command.VCodeDubbeleVereniging), - It.IsAny()), - Times.Once); + exception.Message.Should().Be(ExceptionMessages.VerenigingKanGeenDubbelWordenVanZichzelf); } }