diff --git a/build/azure-pipelines-development-ci-cd.yaml b/build/azure-pipelines-development-ci-cd.yaml index 79af5ed2..e40d9b4c 100644 --- a/build/azure-pipelines-development-ci-cd.yaml +++ b/build/azure-pipelines-development-ci-cd.yaml @@ -13,7 +13,7 @@ pr: none variables: majorVersion: '0' minorVersion: '4' - patchVersion: '4' + patchVersion: '5' feedVersion: 'alpha' dayOfYear: $(DayOfYear) revision: $(Rev:r) diff --git a/build/azure-pipelines-master-ci-cd.yaml b/build/azure-pipelines-master-ci-cd.yaml index 96c508ac..d6332da7 100644 --- a/build/azure-pipelines-master-ci-cd.yaml +++ b/build/azure-pipelines-master-ci-cd.yaml @@ -13,7 +13,7 @@ pr: none variables: majorVersion: '0' minorVersion: '4' - patchVersion: '4' + patchVersion: '5' feedVersion: 'prerelease' dayOfYear: $(DayOfYear) revision: $(Rev:r) diff --git a/build/azure-pipelines-release-ci-cd.yaml b/build/azure-pipelines-release-ci-cd.yaml index 20e59bf6..485361ce 100644 --- a/build/azure-pipelines-release-ci-cd.yaml +++ b/build/azure-pipelines-release-ci-cd.yaml @@ -10,7 +10,7 @@ pr: none variables: majorVersion: '0' minorVersion: '4' - patchVersion: '4' + patchVersion: '5' name: ${{ format('{0}.{1}.{2}', variables.majorVersion, variables.minorVersion, variables.patchVersion) }} diff --git a/examples/web/Akkatecture.Examples.Api/Domain/Aggregates/Resource/Commands/CreateResourceCommand.cs b/examples/web/Akkatecture.Examples.Api/Domain/Aggregates/Resource/Commands/CreateResourceCommand.cs index e8e1a283..14a79ea9 100644 --- a/examples/web/Akkatecture.Examples.Api/Domain/Aggregates/Resource/Commands/CreateResourceCommand.cs +++ b/examples/web/Akkatecture.Examples.Api/Domain/Aggregates/Resource/Commands/CreateResourceCommand.cs @@ -55,7 +55,7 @@ public override void Handle( } else { - var executionResult = new FailedExecutionResult("aggregate is already created"); + var executionResult = new FailedExecutionResult(new List{"aggregate is already created"}); context.Sender.Tell(executionResult); } } diff --git a/src/Akkatecture/Aggregates/DomainEvent.cs b/src/Akkatecture/Aggregates/DomainEvent.cs index d204bd21..46513b56 100644 --- a/src/Akkatecture/Aggregates/DomainEvent.cs +++ b/src/Akkatecture/Aggregates/DomainEvent.cs @@ -43,13 +43,13 @@ public class DomainEvent : IDomainEvent< public TIdentity AggregateIdentity { get; } public TAggregateEvent AggregateEvent { get; } public long AggregateSequenceNumber { get; } - public IMetadata Metadata { get; } + public Metadata Metadata { get; } public DateTimeOffset Timestamp { get; } public DomainEvent( TIdentity aggregateIdentity, TAggregateEvent aggregateEvent, - IMetadata metadata, + Metadata metadata, DateTimeOffset timestamp, long aggregateSequenceNumber) { diff --git a/src/Akkatecture/Aggregates/ExecutionResults/ExecutionResult.cs b/src/Akkatecture/Aggregates/ExecutionResults/ExecutionResult.cs index 3653a831..48fdd3d5 100644 --- a/src/Akkatecture/Aggregates/ExecutionResults/ExecutionResult.cs +++ b/src/Akkatecture/Aggregates/ExecutionResults/ExecutionResult.cs @@ -33,7 +33,7 @@ namespace Akkatecture.Aggregates.ExecutionResults public abstract class ExecutionResult : IExecutionResult { private static readonly IExecutionResult SuccessResult = new SuccessExecutionResult(); - private static readonly IExecutionResult FailedResult = new FailedExecutionResult(); + private static readonly IExecutionResult FailedResult = new FailedExecutionResult(Enumerable.Empty()); public static IExecutionResult Success() => SuccessResult; public static IExecutionResult Failed() => FailedResult; diff --git a/src/Akkatecture/Aggregates/ExecutionResults/FailedExecutionResult.cs b/src/Akkatecture/Aggregates/ExecutionResults/FailedExecutionResult.cs index cf67db81..adaa9644 100644 --- a/src/Akkatecture/Aggregates/ExecutionResults/FailedExecutionResult.cs +++ b/src/Akkatecture/Aggregates/ExecutionResults/FailedExecutionResult.cs @@ -33,13 +33,7 @@ namespace Akkatecture.Aggregates.ExecutionResults public class FailedExecutionResult : ExecutionResult { public IReadOnlyCollection Errors { get; } - - public FailedExecutionResult( - params string[] errors) - : this(errors.ToList()) - { - } - + public FailedExecutionResult( IEnumerable errors) { diff --git a/src/Akkatecture/Aggregates/IDomainEvent.cs b/src/Akkatecture/Aggregates/IDomainEvent.cs index 87a7896b..3f1601f2 100644 --- a/src/Akkatecture/Aggregates/IDomainEvent.cs +++ b/src/Akkatecture/Aggregates/IDomainEvent.cs @@ -36,7 +36,7 @@ public interface IDomainEvent Type IdentityType { get; } Type EventType { get; } long AggregateSequenceNumber { get; } - IMetadata Metadata { get; } + Metadata Metadata { get; } DateTimeOffset Timestamp { get; } IIdentity GetIdentity(); diff --git a/test/Akkatecture.TestHelpers/Aggregates/Commands/TestFailedExecutionResultCommand.cs b/test/Akkatecture.TestHelpers/Aggregates/Commands/TestFailedExecutionResultCommand.cs new file mode 100644 index 00000000..6f6a7c81 --- /dev/null +++ b/test/Akkatecture.TestHelpers/Aggregates/Commands/TestFailedExecutionResultCommand.cs @@ -0,0 +1,14 @@ +using Akkatecture.Commands; + +namespace Akkatecture.TestHelpers.Aggregates.Commands +{ + public class TestFailedExecutionResultCommand : Command + { + public TestFailedExecutionResultCommand( + TestAggregateId aggregateId, + CommandId sourceId) + : base(aggregateId, sourceId) + { + } + } +} \ No newline at end of file diff --git a/test/Akkatecture.TestHelpers/Aggregates/Commands/TestSuccessExecutionResultCommand.cs b/test/Akkatecture.TestHelpers/Aggregates/Commands/TestSuccessExecutionResultCommand.cs new file mode 100644 index 00000000..05918c08 --- /dev/null +++ b/test/Akkatecture.TestHelpers/Aggregates/Commands/TestSuccessExecutionResultCommand.cs @@ -0,0 +1,14 @@ +using Akkatecture.Commands; + +namespace Akkatecture.TestHelpers.Aggregates.Commands +{ + public class TestSuccessExecutionResultCommand : Command + { + public TestSuccessExecutionResultCommand( + TestAggregateId aggregateId, + CommandId sourceId) + : base(aggregateId, sourceId) + { + } + } +} \ No newline at end of file diff --git a/test/Akkatecture.TestHelpers/Aggregates/TestAggregate.cs b/test/Akkatecture.TestHelpers/Aggregates/TestAggregate.cs index 451ca423..abc4f372 100644 --- a/test/Akkatecture.TestHelpers/Aggregates/TestAggregate.cs +++ b/test/Akkatecture.TestHelpers/Aggregates/TestAggregate.cs @@ -59,6 +59,8 @@ public TestAggregate(TestAggregateId aggregateId) Command(Execute); Command(Execute); Command(Execute); + Command(Execute); + Command(Execute); Command(SnapshotStatus); @@ -158,7 +160,17 @@ private bool Execute(ReceiveTestCommand command) return true; } - + private bool Execute(TestFailedExecutionResultCommand command) + { + Sender.Tell(ExecutionResult.Failed(), Self); + return true; + } + + private bool Execute(TestSuccessExecutionResultCommand command) + { + Sender.Tell(ExecutionResult.Success(), Self); + return true; + } private bool Execute(TestDistinctCommand command) { return true; diff --git a/test/Akkatecture.Tests/UnitTests/Aggregates/AggregateTests.cs b/test/Akkatecture.Tests/UnitTests/Aggregates/AggregateTests.cs index b63a5024..ed1aba36 100644 --- a/test/Akkatecture.Tests/UnitTests/Aggregates/AggregateTests.cs +++ b/test/Akkatecture.Tests/UnitTests/Aggregates/AggregateTests.cs @@ -295,7 +295,31 @@ public void TestSnapShotting_AfterManyTests_TestStateSignalled() && x.AggregateEvent.AggregateState.TestCollection.Count == 10 && x.AggregateEvent.AggregateState.FromHydration); } - + + + [Fact] + [Category(Category)] + public async Task InitialState_TestingSuccessCommand_SuccessResultReplied() + { + var aggregateManager = Sys.ActorOf(Props.Create(() => new TestAggregateManager()), "test-aggregatemanager"); + var aggregateId = TestAggregateId.New; + var commandId = CommandId.New; + var command = new TestSuccessExecutionResultCommand(aggregateId, commandId); + + var result = await aggregateManager.Ask(command); + } + + [Fact] + [Category(Category)] + public async Task InitialState_TestingFailedCommand_SuccessResultReplied() + { + var aggregateManager = Sys.ActorOf(Props.Create(() => new TestAggregateManager()), "test-aggregatemanager"); + var aggregateId = TestAggregateId.New; + var commandId = CommandId.New; + var command = new TestFailedExecutionResultCommand(aggregateId, commandId); + + var result = await aggregateManager.Ask(command); + } [Fact] [Category(Category)] public void TestDistinctCommand_AfterTwoHandles_CommandFails() diff --git a/test/Akkatecture.Tests/UnitTests/Serialization/SerializationTests.cs b/test/Akkatecture.Tests/UnitTests/Serialization/SerializationTests.cs index 440417a1..9034e3ee 100644 --- a/test/Akkatecture.Tests/UnitTests/Serialization/SerializationTests.cs +++ b/test/Akkatecture.Tests/UnitTests/Serialization/SerializationTests.cs @@ -22,9 +22,11 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; using Akkatecture.Aggregates; +using Akkatecture.Aggregates.ExecutionResults; using Akkatecture.Aggregates.Snapshot; using Akkatecture.Commands; using Akkatecture.Core; @@ -77,6 +79,38 @@ public void CommittedEvent_AfterSerialization_IsValidAfterDeserialization() committedEvent.SerializeDeserialize().Should().BeEquivalentTo(committedEvent); } + [Fact] + [Category(Category)] + public void DomainEvent_AfterSerialization_IsValidAfterDeserialization() + { + var aggregateSequenceNumber = 3; + var aggregateId = TestAggregateId.New; + var entityId = TestId.New; + var entity = new Test(entityId); + var aggregateEvent = new TestAddedEvent(entity); + var now = DateTimeOffset.UtcNow; + var eventId = EventId.NewDeterministic( + GuidFactories.Deterministic.Namespaces.Events, + $"{aggregateId.Value}-v{aggregateSequenceNumber}"); + var eventMetadata = new Metadata + { + Timestamp = now, + AggregateSequenceNumber = aggregateSequenceNumber, + AggregateName = typeof(TestAggregate).GetAggregateName().Value, + AggregateId = aggregateId.Value, + EventId = eventId + }; + var domainEvent = + new DomainEvent( + aggregateId, + aggregateEvent, + eventMetadata, + now, + aggregateSequenceNumber); + + domainEvent.SerializeDeserialize().Should().BeEquivalentTo(domainEvent); + } + [Fact] [Category(Category)] public void CommittedSnapshot_AfterSerialization_IsValidAfterDeserialization() @@ -128,6 +162,30 @@ public void AddFourTestsCommand_AfterSerialization_IsValidAfterDeserialization() command.SerializeDeserialize().Should().BeEquivalentTo(command); } + + [Fact] + [Category(Category)] + public void FailedExecutionResult_AfterSerialization_IsValidAfterDeserialization() + { + var failureString = "this is a failed execution"; + var executionResult = new FailedExecutionResult(new List{failureString}); + + var result = executionResult.SerializeDeserialize(); + + result.Should().BeEquivalentTo(executionResult); + result.Errors.Should().Equal(failureString); + } + + [Fact] + [Category(Category)] + public void SuccessfulExecutionResult_AfterSerialization_IsValidAfterDeserialization() + { + var executionResult = new SuccessExecutionResult(); + + var result = executionResult.SerializeDeserialize(); + + result.Should().BeEquivalentTo(executionResult); + } }