From 17ef988cff104fd04049a9b275a06bc47ecf8bc6 Mon Sep 17 00:00:00 2001 From: Jur Balledux Date: Mon, 29 Jul 2024 14:56:45 +0200 Subject: [PATCH] Aggregate: Pre process in applied scope (#44) Co-authored-by: Jur Balledux --- props/common.props | 2 +- .../Aggregate_TAggregate.cs | 11 +++-- .../Qowaiv.DomainModel.csproj | 4 +- .../Event_sourced_aggregate_specs.cs | 45 ++++++++++++++++++- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/props/common.props b/props/common.props index dd25279..55d5e8d 100644 --- a/props/common.props +++ b/props/common.props @@ -3,7 +3,7 @@ Qowaiv implements common, universal domain objects. These types form the base of your domain model. - Ad van der Hoeven;Corniel Nobel;Erik Ammerlaan;Jack Kester;Marcel Strik;Mitchell Smit;Patrick Evers;Wilko Frieke + Ad van der Hoeven;Corniel Nobel;Erik Ammerlaan;Jack Kester;Jur Balledux;Marcel Strik;Mitchell Smit;Patrick Evers;Wilko Frieke Qowaiv community qowaiv domain model Qowaiv community diff --git a/src/Qowaiv.DomainModel/Aggregate_TAggregate.cs b/src/Qowaiv.DomainModel/Aggregate_TAggregate.cs index 9f92ec3..7168f0a 100644 --- a/src/Qowaiv.DomainModel/Aggregate_TAggregate.cs +++ b/src/Qowaiv.DomainModel/Aggregate_TAggregate.cs @@ -59,11 +59,14 @@ protected Result ApplyEvents(params object[] events) [Pure] protected Result Apply(IEnumerable events) { - Guard.NotNull(events, nameof(events)); - var updated = Clone(); - var append = AppendOnlyCollection.Empty.Add(events.Select(PreProcessEvent)); - updated.Replay(append); + var append = AppendOnlyCollection.Empty; + + foreach (var @event in Guard.NotNull(events, nameof(events)).Select(updated.PreProcessEvent)) + { + updated.Dispatcher.When(@event); + append = append.Add(@event); + } var result = updated.Validator.Validate(updated); if (result.IsValid) diff --git a/src/Qowaiv.DomainModel/Qowaiv.DomainModel.csproj b/src/Qowaiv.DomainModel/Qowaiv.DomainModel.csproj index b2986d4..152baf9 100644 --- a/src/Qowaiv.DomainModel/Qowaiv.DomainModel.csproj +++ b/src/Qowaiv.DomainModel/Qowaiv.DomainModel.csproj @@ -6,9 +6,11 @@ netstandard2.0;net5.0;net6.0;net7.0;net8.0 library true - 1.1.1 + 1.1.2 Qowaiv.DomainModel +v1.1.2 +- Aggregate: PreProcessEvent in applied scope. #44 v1.1.1 - CommandProcessor made thread-safe. #42 v1.1.0 diff --git a/test/Qowaiv.DomainModel.UnitTests/Event_sourced_aggregate_specs.cs b/test/Qowaiv.DomainModel.UnitTests/Event_sourced_aggregate_specs.cs index d264a7a..e7fc75b 100644 --- a/test/Qowaiv.DomainModel.UnitTests/Event_sourced_aggregate_specs.cs +++ b/test/Qowaiv.DomainModel.UnitTests/Event_sourced_aggregate_specs.cs @@ -1,4 +1,5 @@ -using Qowaiv.DomainModel; +using NUnit.Framework.Internal.Execution; +using Qowaiv.DomainModel; namespace Event_sourced_aggregate_specs { @@ -70,6 +71,21 @@ public void skips_unknown_event_types() var updated = aggregate.TestApplyChange(new NameUpdated("unknown")).Should().BeValid().Value; updated.Version.Should().Be(1); } + + [Test] + public void pre_processed_in_applied_scope() + { + var aggregate = new TestPreProcessEventAggregate(); + var updated = aggregate + .TestPreprocessEvents(new NameUpdated("Jimi Hendrix"), new NameUpdated("unknown")) + .Should().BeValid().Value; + + updated.Buffer.Uncommitted.Should().BeEquivalentTo(new object[] + { + new NameUpdated("Jimi Hendrix"), + new NameUpdated("Jimi Hendrix"), + }); + } } internal class TestApplyChangeAggregate : Aggregate @@ -79,4 +95,31 @@ public TestApplyChangeAggregate() public Result TestApplyChange(object @event) => ApplyEvent(@event); } + + internal class TestPreProcessEventAggregate : Aggregate + { + private string Name = string.Empty; + + public TestPreProcessEventAggregate() + : base(Guid.NewGuid(), Qowaiv.Validation.Abstractions.Validator.Empty()) { } + + public Result TestPreprocessEvents(params object[] events) => ApplyEvents(events); + + protected override object PreProcessEvent(object @event) + { + if (@event is not NameUpdated e) + { + return @event; + } + + var newName = Name == string.Empty ? e.Name : Name; + return new NameUpdated(newName); + } + + + internal void When(NameUpdated @event) + { + Name = @event.Name; + } + } }