From 25328dbfb695af67608ee89a8e63ac26a91122df Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 11:46:46 +0100 Subject: [PATCH 01/21] Update projects to .net8.0 and add KurrentDB --- ...ggregateRepository.EventStore.Tests.csproj | 2 +- .../EventStoreAggregateRepositoryTests.cs | 21 ++++++++------- .../AggregateRepository.EventStore.csproj | 6 ++--- .../EventStoreAggregateRepository.cs | 27 ++++++++++--------- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/AggregateRepository.EventStore.Tests/AggregateRepository.EventStore.Tests.csproj b/src/AggregateRepository.EventStore.Tests/AggregateRepository.EventStore.Tests.csproj index c8331e2..49ea759 100644 --- a/src/AggregateRepository.EventStore.Tests/AggregateRepository.EventStore.Tests.csproj +++ b/src/AggregateRepository.EventStore.Tests/AggregateRepository.EventStore.Tests.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 enable enable diff --git a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs index 32e66cd..635fb3c 100644 --- a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs +++ b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs @@ -9,20 +9,23 @@ namespace CorshamScience.AggregateRepository.EventStore.Tests using System.Runtime.InteropServices; using DotNet.Testcontainers.Images; using DotNet.Testcontainers.Containers; - using global::EventStore.Client; + using KurrentDB.Client; internal class EventStoreAggregateRepositoryTests : AggregateRepositoryTestFixture { private IContainer? _container; - private EventStoreClient? _client; + private KurrentDBClient? _client; protected override async Task InitRepository() { - const string eventStoreVersion = "23.10.0"; - var imageName = RuntimeInformation.OSArchitecture == Architecture.Arm64 - // if on arm (like an m1 mac) use the alpha arm image from github - ? $"ghcr.io/eventstore/eventstore:{eventStoreVersion}-alpha-arm64v8" - : $"eventstore/eventstore:{eventStoreVersion}-bookworm-slim"; + const string eventStoreVersion = "24.10.5"; + + // If on arm (like an m1 mac) use the alpha arm image from github + var architectureSuffix = RuntimeInformation.OSArchitecture == Architecture.Arm64 + ? "-alpha-arm64v8" + : "-bookworm-slim"; + + var imageName = $"eventstore/eventstore:{eventStoreVersion}{architectureSuffix}"; const int hostPort = 2113; @@ -40,10 +43,10 @@ protected override async Task InitRepository() await _container.StartAsync(); - var settings = EventStoreClientSettings + var settings = KurrentDBClientSettings .Create($"esdb://admin:changeit@127.0.0.1:{hostPort}?tls=false"); - _client = new EventStoreClient(settings); + _client = new KurrentDBClient(settings); RepoUnderTest = new EventStoreAggregateRepository(_client); } diff --git a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj b/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj index 2f11f56..2ca9164 100644 --- a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj +++ b/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj @@ -1,7 +1,7 @@ - + - net6.0 + net8.0 enable enable CorshamScience.AggregateRepository.EventStore @@ -37,7 +37,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs index 73d9e9d..e54e00f 100644 --- a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs +++ b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs @@ -2,13 +2,14 @@ // Copyright (c) Corsham Science. All rights reserved. // +using KurrentDB.Client; + namespace CorshamScience.AggregateRepository.EventStore { using System; using System.Text; - using CorshamScience.AggregateRepository.Core; - using CorshamScience.AggregateRepository.Core.Exceptions; - using global::EventStore.Client; + using Core; + using Core.Exceptions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -18,17 +19,17 @@ namespace CorshamScience.AggregateRepository.EventStore /// public class EventStoreAggregateRepository : IAggregateRepository { - private readonly EventStoreClient _eventStoreClient; + private readonly KurrentDBClient _kurrentDbClient; /// - /// Initializes a new instance of the class using the provided to store and retrieve events for an . + /// Initializes a new instance of the class using the provided to store and retrieve events for an . /// - /// The GRPC to connect to. - public EventStoreAggregateRepository(EventStoreClient eventStoreClient) => _eventStoreClient = eventStoreClient; + /// The GRPC to connect to. + public EventStoreAggregateRepository(KurrentDBClient kurrentDbClient) => _kurrentDbClient = kurrentDbClient; /// /// - /// Thrown when the provided 's ID matches a deleted stream in the EventStore the is configured to use. + /// Thrown when the provided 's ID matches a deleted stream in the EventStore the is configured to use. /// public async Task SaveAsync(IAggregate aggregateToSave) { @@ -36,7 +37,7 @@ public async Task SaveAsync(IAggregate aggregateToSave) var streamName = StreamNameForAggregateId(aggregateToSave.Id); var originalVersion = aggregateToSave.Version - events.Count; - ulong expectedVersion = originalVersion == 0 ? expectedVersion = StreamRevision.None : (ulong)(originalVersion - 1); + var expectedVersion = originalVersion == 0 ? StreamState.NoStream : StreamState.StreamRevision((ulong)originalVersion - 1); var preparedEvents = events .Select(ToEventData) @@ -44,7 +45,7 @@ public async Task SaveAsync(IAggregate aggregateToSave) try { - await _eventStoreClient.AppendToStreamAsync(streamName, expectedVersion, preparedEvents) + await _kurrentDbClient.AppendToStreamAsync(streamName, expectedVersion, preparedEvents) .ConfigureAwait(false); aggregateToSave.ClearUncommittedEvents(); } @@ -73,7 +74,7 @@ public async Task GetAggregateAsync(object aggregateId, int version = int. return await CreateAndRehydrateAggregateAsync(events, version).ConfigureAwait(false); } - private static async Task CreateAndRehydrateAggregateAsync(EventStoreClient.ReadStreamResult events, int version) + private static async Task CreateAndRehydrateAggregateAsync(KurrentDBClient.ReadStreamResult events, int version) where T : IAggregate { var aggregate = (T)Activator.CreateInstance(typeof(T), true) !; @@ -144,9 +145,9 @@ private static object Deserialize(ResolvedEvent resolvedEvent) private static string StreamNameForAggregateId(object id) => "aggregate-" + id; - private EventStoreClient.ReadStreamResult ReadFromStream(string streamName, int version) + private KurrentDBClient.ReadStreamResult ReadFromStream(string streamName, int version) { - var events = _eventStoreClient.ReadStreamAsync( + var events = _kurrentDbClient.ReadStreamAsync( Direction.Forwards, streamName, StreamPosition.Start, From 67af5d6f2fe4c17c2388347802f8085dd4b3aca6 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 12:35:27 +0100 Subject: [PATCH 02/21] Target .net48 and latest lang version --- .../AggregateRepository.EventStore.csproj | 3 ++- .../EventStoreAggregateRepository.cs | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj b/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj index 2ca9164..fd8c037 100644 --- a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj +++ b/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj @@ -1,7 +1,8 @@  - net8.0 + net8.0;net48 + latest enable enable CorshamScience.AggregateRepository.EventStore diff --git a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs index e54e00f..d64edf0 100644 --- a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs +++ b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs @@ -15,7 +15,7 @@ namespace CorshamScience.AggregateRepository.EventStore /// /// - /// Implementation of which uses Event Store as underlying storage for an aggregate's events. + /// Implementation of which uses KurrentDB as underlying storage for an aggregate's events. /// public class EventStoreAggregateRepository : IAggregateRepository { @@ -29,7 +29,7 @@ public class EventStoreAggregateRepository : IAggregateRepository /// /// - /// Thrown when the provided 's ID matches a deleted stream in the EventStore the is configured to use. + /// Thrown when the provided 's ID matches a deleted stream in the KurrentDB the is configured to use. /// public async Task SaveAsync(IAggregate aggregateToSave) { @@ -119,8 +119,8 @@ private static object Deserialize(ResolvedEvent resolvedEvent) { const string metaDataPropertyName = "ClrType"; - var jsonData = Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span); - var metaData = Encoding.UTF8.GetString(resolvedEvent.Event.Metadata.Span); + var jsonData = Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span.ToArray()); + var metaData = Encoding.UTF8.GetString(resolvedEvent.Event.Metadata.Span.ToArray()); var eventClrTypeName = JObject.Parse(metaData).Property(metaDataPropertyName)?.Value?.ToObject(); if (eventClrTypeName is null) From 8e1c6ac1f2e85007bba625a92f757f47356d247d Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 12:55:52 +0100 Subject: [PATCH 03/21] Added codestyles and apply formatting --- .editorconfig | 28 -- src/.editorconfig | 212 ++++++++++++ .../AggregateRepositoryTestFixture.cs | 312 +++++++++--------- .../EventStoreAggregateRepositoryTests.cs | 97 +++--- .../TestAggregate.cs | 48 ++- .../TestAggregateCreated.cs | 15 +- .../TestEvent.cs | 18 +- .../Usings.cs | 4 +- .../AggregateRepository.EventStore.csproj | 4 - .../EventStoreAggregateRepository.cs | 253 +++++++------- src/Directory.Build.targets | 5 + 11 files changed, 579 insertions(+), 417 deletions(-) delete mode 100644 .editorconfig create mode 100644 src/.editorconfig create mode 100644 src/Directory.Build.targets diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 83ea7ea..0000000 --- a/.editorconfig +++ /dev/null @@ -1,28 +0,0 @@ -# EditorConfig is awesome:http://EditorConfig.org - -# top-most EditorConfig file -root = true - -# Don't use tabs for indentation. -[*] -indent_style = space -# (Please don't specify an indent_size here; that has too many unintended consequences.) - -# Code files -[*.{cs,csx,vb,vbx}] -indent_size = 4 -insert_final_newline = true -charset = utf-8-bom -max_line_length = 120 - -# Xml project files -[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] -indent_size = 2 - -# Xml config files -[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] -indent_size = 2 - -# JSON files -[*.json] -indent_size = 2 \ No newline at end of file diff --git a/src/.editorconfig b/src/.editorconfig new file mode 100644 index 0000000..f38e0d6 --- /dev/null +++ b/src/.editorconfig @@ -0,0 +1,212 @@ +# editorconfig.org + +# Pharmaxo Scientific .net Codestyles editorconfig v1.0 + +# top-most EditorConfig file +root = true + +# Default settings: +# A newline ending every file +# Use 4 spaces as indentation +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[project.json] +indent_size = 2 + +# C# and Visual Basic files +[*.{cs,vb}] +charset = utf-8-bom + +# Analyzers +dotnet_analyzer_diagnostic.category-Security.severity = warning +dotnet_code_quality.ca1802.api_surface = private, internal + +# Miscellaneous style rules +dotnet_sort_system_directives_first = true +dotnet_style_predefined_type_for_locals_parameters_members = true:warning +dotnet_style_predefined_type_for_member_access = true:warning + +# avoid this. unless absolutely necessary +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# name all constant fields using PascalCase +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = warning +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# static fields should have _ prefix +dotnet_naming_rule.static_fields_should_have_prefix.severity = warning +dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static +dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected +dotnet_naming_style.static_prefix_style.required_prefix = _ +dotnet_naming_style.static_prefix_style.capitalization = camel_case + +# internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# Code quality +dotnet_style_readonly_field = true:warning +dotnet_code_quality_unused_parameters = non_public:warning + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion + +# CA2208: Instantiate argument exceptions correctly +dotnet_diagnostic.CA2208.severity = error + +# C# files +[*.cs] +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Experimental New line rules + +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:warning +dotnet_style_allow_multiple_blank_lines_experimental = false:warning + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current + +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning + +# Code style defaults +csharp_using_directive_placement = outside_namespace:warning +csharp_prefer_braces = true:warning +csharp_preserve_single_line_blocks = true:warning +csharp_preserve_single_line_statements = false:warning +csharp_prefer_static_local_function = true:suggestion +csharp_prefer_simple_using_statement = false:none +csharp_style_prefer_switch_expression = true:suggestion + +# Expression-bodied members +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion +csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion +csharp_style_expression_bodied_local_functions = when_on_single_line:suggestion + +# Pattern matching +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion + +# Null checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Other features +csharp_style_prefer_index_operator = false:none +csharp_style_prefer_range_operator = false:none +csharp_style_pattern_local_over_anonymous_function = false:none + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Namespace preference +csharp_style_namespace_declarations = file_scoped:warning +dotnet_style_namespace_match_folder = true:suggestion + +# Types: Will suggest var in all instances, but does not enforce it. +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = false:none +csharp_style_var_elsewhere = true:suggestion + +# License header (second line required to set severity level for this) +file_header_template = Copyright (c) Pharmaxo. All rights reserved. +dotnet_diagnostic.IDE0073.severity = warning + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml build files +[*.builds] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# Shell scripts +[*.sh] +end_of_line = lf + +[*.{cmd, bat}] +end_of_line = crlf + +# Markdown files +[*.md] + # Double trailing spaces can be used for BR tags, and other instances are enforced by Markdownlint +trim_trailing_whitespace = false diff --git a/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs b/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs index fd01b1e..2868dc3 100644 --- a/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs +++ b/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs @@ -1,200 +1,194 @@ -// -// Copyright (c) Corsham Science. All rights reserved. -// +// Copyright (c) Pharmaxo. All rights reserved. -namespace CorshamScience.AggregateRepository.EventStore.Tests +using CorshamScience.AggregateRepository.Core; +using CorshamScience.AggregateRepository.Core.Exceptions; +using CorshamScience.AggregateRepository.EventStore.Tests; + +namespace AggregateRepository.EventStore.Tests; + +[TestFixture] +public abstract class AggregateRepositoryTestFixture { - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - using CorshamScience.AggregateRepository.Core; - using CorshamScience.AggregateRepository.Core.Exceptions; - using NUnit.Framework; - - [TestFixture] - public abstract class AggregateRepositoryTestFixture + private List _storedEvents = []; + private TestAggregate? _retrievedAggregate; + private string _aggregateIdUnderTest; + + protected IAggregateRepository RepoUnderTest { get; set; } = null!; + + [SetUp] + public async Task SetUp() { - private List _storedEvents = new List(); - private TestAggregate _retrievedAggregate; - private string _aggregateIdUnderTest; + await InitRepository(); + _aggregateIdUnderTest = Guid.NewGuid().ToString(); + _storedEvents = []; + } + + [TearDown] + public async Task TearDown() => await CleanUpRepository(); - protected IAggregateRepository RepoUnderTest { get; set; } + [Test] + public void Retreiving_an_aggregate_from_an_empty_eventstore_should_throw_an_exception() => Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest)); - [SetUp] - public async Task SetUp() + [Test] + public async Task Retreiving_a_nonexistant_aggregate_id_should_throw_an_exception() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + for (var i = 0; i < 2; i++) { - await InitRepository(); - _aggregateIdUnderTest = Guid.NewGuid().ToString(); - _storedEvents = new List(); + var eventId = Guid.NewGuid(); + _storedEvents.Add(eventId); + aggregate.GenerateEvent(eventId); } - [TearDown] - public async Task TearDown() => await CleanUpRepository(); + await RepoUnderTest.SaveAsync(aggregate); + Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(Guid.NewGuid().ToString())); + } + + [Test] + public async Task Retrieving_a_newly_created_aggregate_reconstructs_the_entity_correctly() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + await RepoUnderTest.SaveAsync(aggregate); - [Test] - public void Retreiving_an_aggregate_from_an_empty_eventstore_should_throw_an_exception() => Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest)); + _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); + Assert.That(_retrievedAggregate.Id, Is.EqualTo(_aggregateIdUnderTest)); + Assert.That(_retrievedAggregate.EventsApplied.Count, Is.EqualTo(0)); + } - [Test] - public async Task Retreiving_a_nonexistant_aggregate_id_should_throw_an_exception() + [Test] + public async Task Retrieving_an_aggregate_with_events_reconstructs_the_entity_correctly() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + for (var i = 0; i < 5; i++) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - for (var i = 0; i < 2; i++) - { - var eventId = Guid.NewGuid(); - _storedEvents.Add(eventId); - aggregate.GenerateEvent(eventId); - } - - await RepoUnderTest.SaveAsync(aggregate); - Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(Guid.NewGuid().ToString())); + var eventId = Guid.NewGuid(); + _storedEvents.Add(eventId); + aggregate.GenerateEvent(eventId); } - [Test] - public async Task Retrieving_a_newly_created_aggregate_reconstructs_the_entity_correctly() + await RepoUnderTest.SaveAsync(aggregate); + _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); + + Assert.That(_retrievedAggregate.Id, Is.EqualTo(_aggregateIdUnderTest)); + Assert.That(_retrievedAggregate.EventsApplied.Count, Is.EqualTo(_storedEvents.Count)); + foreach (var id in _storedEvents) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - await RepoUnderTest.SaveAsync(aggregate); + Assert.Contains(id, _retrievedAggregate.EventsApplied); + } + } - _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); - Assert.AreEqual(_aggregateIdUnderTest, _retrievedAggregate.Id); - Assert.AreEqual(0, _retrievedAggregate.EventsApplied.Count); + [Test] + public async Task Retrieving_an_aggregate_with_events_when_specifying_a_version_reconstructs_the_entity_correctly() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + for (var i = 0; i < 5; i++) + { + var eventId = Guid.NewGuid(); + _storedEvents.Add(eventId); + aggregate.GenerateEvent(eventId); } - [Test] - public async Task Retrieving_an_aggregate_with_events_reconstructs_the_entity_correctly() + await RepoUnderTest.SaveAsync(aggregate); + _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest, 6); + + Assert.That(_retrievedAggregate.Id, Is.EqualTo(_aggregateIdUnderTest)); + Assert.That(_retrievedAggregate.EventsApplied.Count, Is.EqualTo(_storedEvents.Count)); + foreach (var id in _storedEvents) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - for (var i = 0; i < 5; i++) - { - var eventId = Guid.NewGuid(); - _storedEvents.Add(eventId); - aggregate.GenerateEvent(eventId); - } - - await RepoUnderTest.SaveAsync(aggregate); - _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); - - Assert.AreEqual(_aggregateIdUnderTest, _retrievedAggregate.Id); - Assert.AreEqual(_storedEvents.Count, _retrievedAggregate.EventsApplied.Count); - foreach (var id in _storedEvents) - { - Assert.Contains(id, _retrievedAggregate.EventsApplied); - } + Assert.Contains(id, _retrievedAggregate.EventsApplied); } + } - [Test] - public async Task Retrieving_an_aggregate_with_events_when_specifying_a_version_reconstructs_the_entity_correctly() + [Test] + public async Task Retrieving_an_aggregate_with_events_reconstructs_the_entity_correctly_when_the_event_store_contains_multiple_aggregates() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + for (var i = 0; i < 5; i++) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - for (var i = 0; i < 5; i++) - { - var eventId = Guid.NewGuid(); - _storedEvents.Add(eventId); - aggregate.GenerateEvent(eventId); - } - - await RepoUnderTest.SaveAsync(aggregate); - _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest, 6); - - Assert.AreEqual(_aggregateIdUnderTest, _retrievedAggregate.Id); - Assert.AreEqual(_storedEvents.Count, _retrievedAggregate.EventsApplied.Count); - foreach (var id in _storedEvents) - { - Assert.Contains(id, _retrievedAggregate.EventsApplied); - } + var eventId = Guid.NewGuid(); + _storedEvents.Add(eventId); + aggregate.GenerateEvent(eventId); } - [Test] - public async Task Retrieving_an_aggregate_with_events_reconstructs_the_entity_correctly_when_the_event_store_contains_multiple_aggregates() + await RepoUnderTest.SaveAsync(aggregate); + var secondAggregate = new TestAggregate(Guid.NewGuid().ToString()); + for (var i = 0; i < 6; i++) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - for (var i = 0; i < 5; i++) - { - var eventId = Guid.NewGuid(); - _storedEvents.Add(eventId); - aggregate.GenerateEvent(eventId); - } - - await RepoUnderTest.SaveAsync(aggregate); - var secondAggregate = new TestAggregate(Guid.NewGuid().ToString()); - for (var i = 0; i < 6; i++) - { - var eventId = Guid.NewGuid(); - secondAggregate.GenerateEvent(eventId); - } - - await RepoUnderTest.SaveAsync(secondAggregate); - _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); - - Assert.AreEqual(_aggregateIdUnderTest, _retrievedAggregate.Id); - Assert.AreEqual(_storedEvents.Count, _retrievedAggregate.EventsApplied.Count); - foreach (var id in _storedEvents) - { - Assert.Contains(id, _retrievedAggregate.EventsApplied); - } + var eventId = Guid.NewGuid(); + secondAggregate.GenerateEvent(eventId); } - [Test] - public async Task Saving_new_events_to_an_existing_aggregate_should_correctly_persist_events() + await RepoUnderTest.SaveAsync(secondAggregate); + _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); + + Assert.That(_retrievedAggregate.Id, Is.EqualTo(_aggregateIdUnderTest)); + Assert.That(_retrievedAggregate.EventsApplied.Count, Is.EqualTo(_storedEvents.Count)); + foreach (var id in _storedEvents) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - await RepoUnderTest.SaveAsync(aggregate); + Assert.Contains(id, _retrievedAggregate.EventsApplied); + } + } - _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); + [Test] + public async Task Saving_new_events_to_an_existing_aggregate_should_correctly_persist_events() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + await RepoUnderTest.SaveAsync(aggregate); - var eventId = Guid.NewGuid(); - _retrievedAggregate.GenerateEvent(eventId); + _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); - await RepoUnderTest.SaveAsync(_retrievedAggregate); - var actualAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); + var eventId = Guid.NewGuid(); + _retrievedAggregate.GenerateEvent(eventId); - Assert.AreEqual(1, actualAggregate.EventsApplied.Count); - Assert.AreEqual(_aggregateIdUnderTest, actualAggregate.Id); - Assert.AreEqual(eventId, actualAggregate.EventsApplied[0]); - } + await RepoUnderTest.SaveAsync(_retrievedAggregate); + var actualAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest); + + Assert.That(actualAggregate.EventsApplied.Count, Is.EqualTo(1)); + Assert.That(actualAggregate.Id, Is.EqualTo(_aggregateIdUnderTest)); + Assert.That(actualAggregate.EventsApplied[0], Is.EqualTo(eventId)); + } - [Test] - public async Task Saving_an_aggregate_with_expected_version_less_than_the_actual_version_should_throw_a_concurrency_exception() + [Test] + public async Task Saving_an_aggregate_with_expected_version_less_than_the_actual_version_should_throw_a_concurrency_exception() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + for (var i = 0; i < 5; i++) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - for (var i = 0; i < 5; i++) - { - var eventId = Guid.NewGuid(); - _storedEvents.Add(eventId); - aggregate.GenerateEvent(eventId); - } - - await RepoUnderTest.SaveAsync(aggregate); - - _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest, 3); - - for (var i = 0; i < 5; i++) - { - var eventId = Guid.NewGuid(); - _storedEvents.Add(eventId); - _retrievedAggregate.GenerateEvent(eventId); - } - - Assert.ThrowsAsync(async () => await RepoUnderTest.SaveAsync(_retrievedAggregate)); + var eventId = Guid.NewGuid(); + _storedEvents.Add(eventId); + aggregate.GenerateEvent(eventId); } - [Test] - public async Task Retrieving_an_aggregate_with_expected_version_greater_than_the_actual_version_should_throw_a_concurrency_exception() + await RepoUnderTest.SaveAsync(aggregate); + + _retrievedAggregate = await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest, 3); + + for (var i = 0; i < 5; i++) { - var aggregate = new TestAggregate(_aggregateIdUnderTest); - for (var i = 0; i < 5; i++) - { - var eventId = Guid.NewGuid(); - _storedEvents.Add(eventId); - aggregate.GenerateEvent(eventId); - } - - await RepoUnderTest.SaveAsync(aggregate); - Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest, 10)); + var eventId = Guid.NewGuid(); + _storedEvents.Add(eventId); + _retrievedAggregate.GenerateEvent(eventId); } - protected abstract Task InitRepository(); + Assert.ThrowsAsync(async () => await RepoUnderTest.SaveAsync(_retrievedAggregate)); + } + + [Test] + public async Task Retrieving_an_aggregate_with_expected_version_greater_than_the_actual_version_should_throw_a_concurrency_exception() + { + var aggregate = new TestAggregate(_aggregateIdUnderTest); + for (var i = 0; i < 5; i++) + { + var eventId = Guid.NewGuid(); + _storedEvents.Add(eventId); + aggregate.GenerateEvent(eventId); + } - protected abstract Task CleanUpRepository(); + await RepoUnderTest.SaveAsync(aggregate); + Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest, 10)); } + + protected abstract Task InitRepository(); + + protected abstract Task CleanUpRepository(); } diff --git a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs index 635fb3c..09fe63a 100644 --- a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs +++ b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs @@ -1,66 +1,63 @@ -// -// Copyright (c) Corsham Science. All rights reserved. -// +// Copyright (c) Pharmaxo. All rights reserved. -namespace CorshamScience.AggregateRepository.EventStore.Tests +using System.Runtime.InteropServices; +using CorshamScience.AggregateRepository.EventStore; +using DotNet.Testcontainers.Builders; +using DotNet.Testcontainers.Containers; +using DotNet.Testcontainers.Images; +using KurrentDB.Client; + +namespace AggregateRepository.EventStore.Tests; + +internal class EventStoreAggregateRepositoryTests : AggregateRepositoryTestFixture { - using CorshamScience.AggregateRepository.EventStore; - using DotNet.Testcontainers.Builders; - using System.Runtime.InteropServices; - using DotNet.Testcontainers.Images; - using DotNet.Testcontainers.Containers; - using KurrentDB.Client; + private IContainer? _container; + private KurrentDBClient? _client; - internal class EventStoreAggregateRepositoryTests : AggregateRepositoryTestFixture + protected override async Task InitRepository() { - private IContainer? _container; - private KurrentDBClient? _client; + const string eventStoreVersion = "24.10.5"; - protected override async Task InitRepository() - { - const string eventStoreVersion = "24.10.5"; + // If on arm (like an m1 mac) use the alpha arm image from github + var architectureSuffix = RuntimeInformation.OSArchitecture == Architecture.Arm64 + ? "-alpha-arm64v8" + : "-bookworm-slim"; - // If on arm (like an m1 mac) use the alpha arm image from github - var architectureSuffix = RuntimeInformation.OSArchitecture == Architecture.Arm64 - ? "-alpha-arm64v8" - : "-bookworm-slim"; + var imageName = $"eventstore/eventstore:{eventStoreVersion}{architectureSuffix}"; - var imageName = $"eventstore/eventstore:{eventStoreVersion}{architectureSuffix}"; - - const int hostPort = 2113; - - _container = new ContainerBuilder() - .WithImage(new DockerImage(imageName)) - .WithCleanUp(true) - .WithPortBinding(hostPort) - .WithEnvironment(new Dictionary - { - { "EVENTSTORE_INSECURE", "true" }, - { "EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "true" }, - }) - .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(hostPort)) - .Build(); + const int hostPort = 2113; - await _container.StartAsync(); + _container = new ContainerBuilder() + .WithImage(new DockerImage(imageName)) + .WithCleanUp(true) + .WithPortBinding(hostPort) + .WithEnvironment(new Dictionary + { + { "EVENTSTORE_INSECURE", "true" }, + { "EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "true" }, + }) + .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(hostPort)) + .Build(); - var settings = KurrentDBClientSettings - .Create($"esdb://admin:changeit@127.0.0.1:{hostPort}?tls=false"); + await _container.StartAsync(); - _client = new KurrentDBClient(settings); - RepoUnderTest = new EventStoreAggregateRepository(_client); - } + var settings = KurrentDBClientSettings + .Create($"esdb://admin:changeit@127.0.0.1:{hostPort}?tls=false"); - protected override async Task CleanUpRepository() + _client = new KurrentDBClient(settings); + RepoUnderTest = new EventStoreAggregateRepository(_client); + } + + protected override async Task CleanUpRepository() + { + if (_container != null) { - if (_container != null) - { - await _container.DisposeAsync(); - } + await _container.DisposeAsync(); + } - if (_client != null) - { - await _client.DisposeAsync(); - } + if (_client != null) + { + await _client.DisposeAsync(); } } } diff --git a/src/AggregateRepository.EventStore.Tests/TestAggregate.cs b/src/AggregateRepository.EventStore.Tests/TestAggregate.cs index 64e0d35..c363d8d 100644 --- a/src/AggregateRepository.EventStore.Tests/TestAggregate.cs +++ b/src/AggregateRepository.EventStore.Tests/TestAggregate.cs @@ -1,37 +1,33 @@ -// -// Copyright (c) Corsham Science. All rights reserved. -// +// Copyright (c) Pharmaxo. All rights reserved. -namespace CorshamScience.AggregateRepository.EventStore.Tests -{ - using CorshamScience.AggregateRepository.Core; +using CorshamScience.AggregateRepository.Core; - internal sealed class TestAggregate : AggregateBase - { - private object _id = null!; +namespace CorshamScience.AggregateRepository.EventStore.Tests; +internal sealed class TestAggregate : AggregateBase +{ + private object _id = null!; - public TestAggregate(string aggregateId) => RaiseEvent(new TestAggregateCreated(aggregateId)); + public TestAggregate(string aggregateId) => RaiseEvent(new TestAggregateCreated(aggregateId)); - // ReSharper disable once UnusedMember.Local - private TestAggregate() - { - } + // ReSharper disable once UnusedMember.Local + private TestAggregate() + { + } - // ReSharper disable once ConvertToAutoPropertyWithPrivateSetter - public override object Id => _id; + // ReSharper disable once ConvertToAutoPropertyWithPrivateSetter + public override object Id => _id; - public List EventsApplied { get; } = new List(); + public List EventsApplied { get; } = new List(); - protected override EventMap Map => new EventMap - { - [typeof(TestEvent)] = e => Apply((TestEvent)e), - [typeof(TestAggregateCreated)] = e => Apply((TestAggregateCreated)e), - }; + protected override EventMap Map => new EventMap + { + [typeof(TestEvent)] = e => Apply((TestEvent)e), + [typeof(TestAggregateCreated)] = e => Apply((TestAggregateCreated)e), + }; - public void Apply(TestEvent e) => EventsApplied.Add(e.EventId); + public void Apply(TestEvent e) => EventsApplied.Add(e.EventId); - public void Apply(TestAggregateCreated e) => _id = e.AggregateId; + public void Apply(TestAggregateCreated e) => _id = e.AggregateId; - public void GenerateEvent(Guid eventId) => RaiseEvent(new TestEvent(eventId)); - } + public void GenerateEvent(Guid eventId) => RaiseEvent(new TestEvent(eventId)); } diff --git a/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs b/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs index 347a9eb..0299fef 100644 --- a/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs +++ b/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs @@ -1,13 +1,10 @@ -// -// Copyright (c) Corsham Science. All rights reserved. -// +// Copyright (c) Pharmaxo. All rights reserved. -namespace CorshamScience.AggregateRepository.EventStore.Tests +namespace CorshamScience.AggregateRepository.EventStore.Tests; + +internal class TestAggregateCreated { - internal class TestAggregateCreated - { - public TestAggregateCreated(object aggregateId) => AggregateId = aggregateId; + public TestAggregateCreated(object aggregateId) => AggregateId = aggregateId; - public object AggregateId { get; } - } + public object AggregateId { get; } } diff --git a/src/AggregateRepository.EventStore.Tests/TestEvent.cs b/src/AggregateRepository.EventStore.Tests/TestEvent.cs index 2b83ef6..4178d19 100644 --- a/src/AggregateRepository.EventStore.Tests/TestEvent.cs +++ b/src/AggregateRepository.EventStore.Tests/TestEvent.cs @@ -1,15 +1,11 @@ -// -// Copyright (c) Corsham Science. All rights reserved. -// +// Copyright (c) Pharmaxo. All rights reserved. -namespace CorshamScience.AggregateRepository.EventStore.Tests -{ - using System; +using System; - internal class TestEvent - { - public TestEvent(Guid eventId) => EventId = eventId; +namespace CorshamScience.AggregateRepository.EventStore.Tests; +internal class TestEvent +{ + public TestEvent(Guid eventId) => EventId = eventId; - public Guid EventId { get; } - } + public Guid EventId { get; } } diff --git a/src/AggregateRepository.EventStore.Tests/Usings.cs b/src/AggregateRepository.EventStore.Tests/Usings.cs index cefced4..e8f0746 100644 --- a/src/AggregateRepository.EventStore.Tests/Usings.cs +++ b/src/AggregateRepository.EventStore.Tests/Usings.cs @@ -1 +1,3 @@ -global using NUnit.Framework; \ No newline at end of file +// Copyright (c) Pharmaxo. All rights reserved. + +global using NUnit.Framework; diff --git a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj b/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj index fd8c037..dcc1c44 100644 --- a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj +++ b/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj @@ -34,10 +34,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs index d64edf0..93bcfd5 100644 --- a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs +++ b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs @@ -1,164 +1,159 @@ -// -// Copyright (c) Corsham Science. All rights reserved. -// +// Copyright (c) Pharmaxo. All rights reserved. +using System.Text; +using CorshamScience.AggregateRepository.Core; +using CorshamScience.AggregateRepository.Core.Exceptions; using KurrentDB.Client; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; -namespace CorshamScience.AggregateRepository.EventStore +namespace CorshamScience.AggregateRepository.EventStore; + +/// +/// +/// Implementation of which uses KurrentDB as underlying storage for an aggregate's events. +/// +public class EventStoreAggregateRepository : IAggregateRepository { - using System; - using System.Text; - using Core; - using Core.Exceptions; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; + private readonly KurrentDBClient _kurrentDbClient; - /// /// - /// Implementation of which uses KurrentDB as underlying storage for an aggregate's events. + /// Initializes a new instance of the class using the provided to store and retrieve events for an . /// - public class EventStoreAggregateRepository : IAggregateRepository + /// The GRPC to connect to. + public EventStoreAggregateRepository(KurrentDBClient kurrentDbClient) => _kurrentDbClient = kurrentDbClient; + + /// + /// + /// Thrown when the provided 's ID matches a deleted stream in the KurrentDB the is configured to use. + /// + public async Task SaveAsync(IAggregate aggregateToSave) { - private readonly KurrentDBClient _kurrentDbClient; - - /// - /// Initializes a new instance of the class using the provided to store and retrieve events for an . - /// - /// The GRPC to connect to. - public EventStoreAggregateRepository(KurrentDBClient kurrentDbClient) => _kurrentDbClient = kurrentDbClient; - - /// - /// - /// Thrown when the provided 's ID matches a deleted stream in the KurrentDB the is configured to use. - /// - public async Task SaveAsync(IAggregate aggregateToSave) + var events = aggregateToSave.GetUncommittedEvents().Cast().ToList(); + var streamName = StreamNameForAggregateId(aggregateToSave.Id); + + var originalVersion = aggregateToSave.Version - events.Count; + var expectedVersion = originalVersion == 0 ? StreamState.NoStream : StreamState.StreamRevision((ulong)originalVersion - 1); + + var preparedEvents = events + .Select(ToEventData) + .ToArray(); + + try { - var events = aggregateToSave.GetUncommittedEvents().Cast().ToList(); - var streamName = StreamNameForAggregateId(aggregateToSave.Id); - - var originalVersion = aggregateToSave.Version - events.Count; - var expectedVersion = originalVersion == 0 ? StreamState.NoStream : StreamState.StreamRevision((ulong)originalVersion - 1); - - var preparedEvents = events - .Select(ToEventData) - .ToArray(); - - try - { - await _kurrentDbClient.AppendToStreamAsync(streamName, expectedVersion, preparedEvents) - .ConfigureAwait(false); - aggregateToSave.ClearUncommittedEvents(); - } - catch (StreamDeletedException ex) - { - throw new AggregateNotFoundException("Aggregate not found, stream deleted", ex); - } - catch (WrongExpectedVersionException ex) - { - throw new AggregateVersionException("Aggregate version incorrect", ex); - } + await _kurrentDbClient.AppendToStreamAsync(streamName, expectedVersion, preparedEvents) + .ConfigureAwait(false); + aggregateToSave.ClearUncommittedEvents(); } + catch (StreamDeletedException ex) + { + throw new AggregateNotFoundException("Aggregate not found, stream deleted", ex); + } + catch (WrongExpectedVersionException ex) + { + throw new AggregateVersionException("Aggregate version incorrect", ex); + } + } - /// - public async Task GetAggregateAsync(object aggregateId, int version = int.MaxValue) - where T : IAggregate + /// + public async Task GetAggregateAsync(object aggregateId, int version = int.MaxValue) + where T : IAggregate + { + if (version <= 0) { - if (version <= 0) - { - throw new InvalidOperationException("Cannot get version <= 0"); - } + throw new InvalidOperationException("Cannot get version <= 0"); + } + + var streamName = StreamNameForAggregateId(aggregateId); + var events = ReadFromStream(streamName, version); + + return await CreateAndRehydrateAggregateAsync(events, version).ConfigureAwait(false); + } + + private static async Task CreateAndRehydrateAggregateAsync(KurrentDBClient.ReadStreamResult events, int version) + where T : IAggregate + { + var aggregate = (T)Activator.CreateInstance(typeof(T), true)!; - var streamName = StreamNameForAggregateId(aggregateId); - var events = ReadFromStream(streamName, version); + var eventCount = 0; - return await CreateAndRehydrateAggregateAsync(events, version).ConfigureAwait(false); + await foreach (var @event in events.ConfigureAwait(false)) + { + eventCount++; + aggregate.ApplyEvent(Deserialize(@event)); } - private static async Task CreateAndRehydrateAggregateAsync(KurrentDBClient.ReadStreamResult events, int version) - where T : IAggregate + // If version is greater than number of events, throw exception + if (eventCount < version && version != int.MaxValue) { - var aggregate = (T)Activator.CreateInstance(typeof(T), true) !; + throw new AggregateVersionException("version is higher than actual version"); + } - var eventCount = 0; + return aggregate; + } - await foreach (var @event in events.ConfigureAwait(false)) - { - eventCount++; - aggregate.ApplyEvent(Deserialize(@event)); - } + private static EventData ToEventData(object @event) + { + var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(@event)); - // If version is greater than number of events, throw exception - if (eventCount < version && version != int.MaxValue) - { - throw new AggregateVersionException("version is higher than actual version"); - } + var eventHeaders = new + { + ClrType = @event.GetType().AssemblyQualifiedName + }; - return aggregate; - } + var metadata = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventHeaders)); + var typeName = @event.GetType().Name; - private static EventData ToEventData(object @event) - { - var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(@event)); + return new( + Uuid.NewUuid(), + typeName, + data, + metadata); + } - var eventHeaders = new - { - ClrType = @event.GetType().AssemblyQualifiedName, - }; + private static object Deserialize(ResolvedEvent resolvedEvent) + { + const string metaDataPropertyName = "ClrType"; - var metadata = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventHeaders)); - var typeName = @event.GetType().Name; + var jsonData = Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span.ToArray()); + var metaData = Encoding.UTF8.GetString(resolvedEvent.Event.Metadata.Span.ToArray()); + var eventClrTypeName = JObject.Parse(metaData).Property(metaDataPropertyName)?.Value.ToObject(); - return new ( - Uuid.NewUuid(), - typeName, - data, - metadata); + if (eventClrTypeName is null) + { + throw new InvalidOperationException($"Event Metadata has no property '{metaDataPropertyName}'"); } - private static object Deserialize(ResolvedEvent resolvedEvent) + var type = Type.GetType(eventClrTypeName); + if (type is null) { - const string metaDataPropertyName = "ClrType"; - - var jsonData = Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span.ToArray()); - var metaData = Encoding.UTF8.GetString(resolvedEvent.Event.Metadata.Span.ToArray()); - var eventClrTypeName = JObject.Parse(metaData).Property(metaDataPropertyName)?.Value?.ToObject(); - - if (eventClrTypeName is null) - { - throw new InvalidOperationException($"Event Metadata has no property '{metaDataPropertyName}'"); - } - - var type = Type.GetType(eventClrTypeName); - if (type is null) - { - throw new InvalidOperationException($"Could not find type ${eventClrTypeName}"); - } - - var deserialized = JsonConvert.DeserializeObject(jsonData, type); - if (deserialized is null) - { - throw new InvalidOperationException($"Failed to deserialize event of type ${eventClrTypeName}"); - } - - return deserialized; + throw new InvalidOperationException($"Could not find type ${eventClrTypeName}"); } - private static string StreamNameForAggregateId(object id) => "aggregate-" + id; + var deserialized = JsonConvert.DeserializeObject(jsonData, type); + if (deserialized is null) + { + throw new InvalidOperationException($"Failed to deserialize event of type ${eventClrTypeName}"); + } + + return deserialized; + } - private KurrentDBClient.ReadStreamResult ReadFromStream(string streamName, int version) + private static string StreamNameForAggregateId(object id) => "aggregate-" + id; + + private KurrentDBClient.ReadStreamResult ReadFromStream(string streamName, int version) + { + var events = _kurrentDbClient.ReadStreamAsync( + Direction.Forwards, + streamName, + StreamPosition.Start, + version); + + if (events.ReadState.Result != ReadState.Ok) { - var events = _kurrentDbClient.ReadStreamAsync( - Direction.Forwards, - streamName, - StreamPosition.Start, - version); - - if (events.ReadState.Result != ReadState.Ok) - { - throw new AggregateNotFoundException(streamName); - } - - return events; + throw new AggregateNotFoundException(streamName); } + + return events; } } diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets new file mode 100644 index 0000000..80f498a --- /dev/null +++ b/src/Directory.Build.targets @@ -0,0 +1,5 @@ + + + true + + From 402f0d66ea2e53f0e991844b842568d1092470de Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 13:13:03 +0100 Subject: [PATCH 04/21] Renamed to current Kurrent and replaced CorshamScience with PharmaxoScientific --- ...oj => AggregateRepository.Kurrent.Tests.csproj} | 2 +- .../AggregateRepositoryTestFixture.cs | 3 +-- .../EventStoreAggregateRepositoryTests.cs | 4 ++-- .../TestAggregate.cs | 3 ++- .../TestAggregateCreated.cs | 2 +- .../TestEvent.cs | 3 +-- ...e.csproj => AggregateRepository.Kurrent.csproj} | 14 +++++++------- .../EventStoreAggregateRepository.cs | 2 +- ...ntStore.sln => AggregateRepository.Kurrent.sln} | 4 ++-- 9 files changed, 18 insertions(+), 19 deletions(-) rename src/AggregateRepository.EventStore.Tests/{AggregateRepository.EventStore.Tests.csproj => AggregateRepository.Kurrent.Tests.csproj} (96%) rename src/AggregateRepository.EventStore/{AggregateRepository.EventStore.csproj => AggregateRepository.Kurrent.csproj} (76%) rename src/{AggregateRepository.EventStore.sln => AggregateRepository.Kurrent.sln} (83%) diff --git a/src/AggregateRepository.EventStore.Tests/AggregateRepository.EventStore.Tests.csproj b/src/AggregateRepository.EventStore.Tests/AggregateRepository.Kurrent.Tests.csproj similarity index 96% rename from src/AggregateRepository.EventStore.Tests/AggregateRepository.EventStore.Tests.csproj rename to src/AggregateRepository.EventStore.Tests/AggregateRepository.Kurrent.Tests.csproj index 49ea759..29e3ffb 100644 --- a/src/AggregateRepository.EventStore.Tests/AggregateRepository.EventStore.Tests.csproj +++ b/src/AggregateRepository.EventStore.Tests/AggregateRepository.Kurrent.Tests.csproj @@ -26,7 +26,7 @@ - + diff --git a/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs b/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs index 2868dc3..0617c45 100644 --- a/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs +++ b/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs @@ -2,9 +2,8 @@ using CorshamScience.AggregateRepository.Core; using CorshamScience.AggregateRepository.Core.Exceptions; -using CorshamScience.AggregateRepository.EventStore.Tests; -namespace AggregateRepository.EventStore.Tests; +namespace AggregateRepository.Kurrent.Tests; [TestFixture] public abstract class AggregateRepositoryTestFixture diff --git a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs index 09fe63a..565678e 100644 --- a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs +++ b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs @@ -1,13 +1,13 @@ // Copyright (c) Pharmaxo. All rights reserved. using System.Runtime.InteropServices; -using CorshamScience.AggregateRepository.EventStore; using DotNet.Testcontainers.Builders; using DotNet.Testcontainers.Containers; using DotNet.Testcontainers.Images; using KurrentDB.Client; +using PharmaxoScientific.AggregateRepository.Kurrent; -namespace AggregateRepository.EventStore.Tests; +namespace AggregateRepository.Kurrent.Tests; internal class EventStoreAggregateRepositoryTests : AggregateRepositoryTestFixture { diff --git a/src/AggregateRepository.EventStore.Tests/TestAggregate.cs b/src/AggregateRepository.EventStore.Tests/TestAggregate.cs index c363d8d..8156ecc 100644 --- a/src/AggregateRepository.EventStore.Tests/TestAggregate.cs +++ b/src/AggregateRepository.EventStore.Tests/TestAggregate.cs @@ -2,7 +2,8 @@ using CorshamScience.AggregateRepository.Core; -namespace CorshamScience.AggregateRepository.EventStore.Tests; +namespace AggregateRepository.Kurrent.Tests; + internal sealed class TestAggregate : AggregateBase { private object _id = null!; diff --git a/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs b/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs index 0299fef..f856f3b 100644 --- a/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs +++ b/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs @@ -1,6 +1,6 @@ // Copyright (c) Pharmaxo. All rights reserved. -namespace CorshamScience.AggregateRepository.EventStore.Tests; +namespace AggregateRepository.Kurrent.Tests; internal class TestAggregateCreated { diff --git a/src/AggregateRepository.EventStore.Tests/TestEvent.cs b/src/AggregateRepository.EventStore.Tests/TestEvent.cs index 4178d19..672e0f2 100644 --- a/src/AggregateRepository.EventStore.Tests/TestEvent.cs +++ b/src/AggregateRepository.EventStore.Tests/TestEvent.cs @@ -1,8 +1,7 @@ // Copyright (c) Pharmaxo. All rights reserved. -using System; +namespace AggregateRepository.Kurrent.Tests; -namespace CorshamScience.AggregateRepository.EventStore.Tests; internal class TestEvent { public TestEvent(Guid eventId) => EventId = eventId; diff --git a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj b/src/AggregateRepository.EventStore/AggregateRepository.Kurrent.csproj similarity index 76% rename from src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj rename to src/AggregateRepository.EventStore/AggregateRepository.Kurrent.csproj index dcc1c44..292abf0 100644 --- a/src/AggregateRepository.EventStore/AggregateRepository.EventStore.csproj +++ b/src/AggregateRepository.EventStore/AggregateRepository.Kurrent.csproj @@ -5,19 +5,19 @@ latest enable enable - CorshamScience.AggregateRepository.EventStore - CorshamScience.AggregateRepository.EventStore + PharmaxoScientific.AggregateRepository.Kurrent + PharmaxoScientific.AggregateRepository.Kurrent Corsham Science Corsham Science - EventStore implementation for saving and rebuilding objects from event streams. - Corsham Science 2022 + KurrentDB implementation for saving and rebuilding objects from event streams. + PharmaxoScientific 2025 https://github.com/qphl/AggregateRepository.EventStore https://github.com/qphl/AggregateRepository.EventStore https://raw.githubusercontent.com/qphl/AggregateRepository.EventStore/master/logo.png - Event Store, Event Sourcing, Aggregate Repository - CorshamScience.AggregateRepository + Event Store, KurrentDB, Event Sourcing, Aggregate Repository + PharmaxoScientific.AggregateRepository https://GitHub.com/qphl/AggregateRepository.EventStore/releases/tag/ - CorshamScience.AggregateRepository.EventStore + PharmaxoScientific.AggregateRepository.Kurrent BSD-3-Clause Logo.png diff --git a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs index 93bcfd5..2c55fff 100644 --- a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs +++ b/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace CorshamScience.AggregateRepository.EventStore; +namespace PharmaxoScientific.AggregateRepository.Kurrent; /// /// diff --git a/src/AggregateRepository.EventStore.sln b/src/AggregateRepository.Kurrent.sln similarity index 83% rename from src/AggregateRepository.EventStore.sln rename to src/AggregateRepository.Kurrent.sln index e4be82a..f39fa1e 100644 --- a/src/AggregateRepository.EventStore.sln +++ b/src/AggregateRepository.Kurrent.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.EventStore", "AggregateRepository.EventStore\AggregateRepository.EventStore.csproj", "{84A2B093-71F2-4015-94E1-5188AD8AEDF6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent", "AggregateRepository.EventStore\AggregateRepository.Kurrent.csproj", "{84A2B093-71F2-4015-94E1-5188AD8AEDF6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.EventStore.Tests", "AggregateRepository.EventStore.Tests\AggregateRepository.EventStore.Tests.csproj", "{5870B925-53E3-4B53-9975-46F508F11445}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent.Tests", "AggregateRepository.EventStore.Tests\AggregateRepository.Kurrent.Tests.csproj", "{5870B925-53E3-4B53-9975-46F508F11445}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From 29e2fd04f9d427912bb8cd09850c4f3d2a574eab Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 13:20:48 +0100 Subject: [PATCH 05/21] Renamed aggregate repository --- .../AggregateRepositoryTestFixture.cs | 2 +- .../EventStoreAggregateRepositoryTests.cs | 4 ++-- ...gregateRepository.cs => KurrentDbAggregateRepository.cs} | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/AggregateRepository.EventStore/{EventStoreAggregateRepository.cs => KurrentDbAggregateRepository.cs} (93%) diff --git a/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs b/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs index 0617c45..ab3ba55 100644 --- a/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs +++ b/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs @@ -26,7 +26,7 @@ public async Task SetUp() public async Task TearDown() => await CleanUpRepository(); [Test] - public void Retreiving_an_aggregate_from_an_empty_eventstore_should_throw_an_exception() => Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest)); + public void Retreiving_an_aggregate_from_an_empty_kurrentdb_should_throw_an_exception() => Assert.ThrowsAsync(async () => await RepoUnderTest.GetAggregateAsync(_aggregateIdUnderTest)); [Test] public async Task Retreiving_a_nonexistant_aggregate_id_should_throw_an_exception() diff --git a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs index 565678e..31ddfe5 100644 --- a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs +++ b/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs @@ -9,7 +9,7 @@ namespace AggregateRepository.Kurrent.Tests; -internal class EventStoreAggregateRepositoryTests : AggregateRepositoryTestFixture +internal class KurrentDbAggregateRepositoryTests : AggregateRepositoryTestFixture { private IContainer? _container; private KurrentDBClient? _client; @@ -45,7 +45,7 @@ protected override async Task InitRepository() .Create($"esdb://admin:changeit@127.0.0.1:{hostPort}?tls=false"); _client = new KurrentDBClient(settings); - RepoUnderTest = new EventStoreAggregateRepository(_client); + RepoUnderTest = new KurrentDbAggregateRepository(_client); } protected override async Task CleanUpRepository() diff --git a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs b/src/AggregateRepository.EventStore/KurrentDbAggregateRepository.cs similarity index 93% rename from src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs rename to src/AggregateRepository.EventStore/KurrentDbAggregateRepository.cs index 2c55fff..9e11617 100644 --- a/src/AggregateRepository.EventStore/EventStoreAggregateRepository.cs +++ b/src/AggregateRepository.EventStore/KurrentDbAggregateRepository.cs @@ -13,15 +13,15 @@ namespace PharmaxoScientific.AggregateRepository.Kurrent; /// /// Implementation of which uses KurrentDB as underlying storage for an aggregate's events. /// -public class EventStoreAggregateRepository : IAggregateRepository +public class KurrentDbAggregateRepository : IAggregateRepository { private readonly KurrentDBClient _kurrentDbClient; /// - /// Initializes a new instance of the class using the provided to store and retrieve events for an . + /// Initializes a new instance of the class using the provided to store and retrieve events for an . /// /// The GRPC to connect to. - public EventStoreAggregateRepository(KurrentDBClient kurrentDbClient) => _kurrentDbClient = kurrentDbClient; + public KurrentDbAggregateRepository(KurrentDBClient kurrentDbClient) => _kurrentDbClient = kurrentDbClient; /// /// From 0746cf32852c99e6745ac0c9c6f239d10c4c3aee Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 13:32:04 +0100 Subject: [PATCH 06/21] More reference updated from EventStore to Kurrent --- build.cmd | 6 +++--- build.sh | 4 ++-- .../AggregateRepository.Kurrent.Tests.csproj | 2 +- .../AggregateRepositoryTestFixture.cs | 0 .../EventStoreAggregateRepositoryTests.cs | 0 .../TestAggregate.cs | 0 .../TestAggregateCreated.cs | 0 .../TestEvent.cs | 0 .../Usings.cs | 0 src/AggregateRepository.Kurrent.sln | 4 ++-- .../AggregateRepository.Kurrent.csproj | 4 ++-- .../KurrentDbAggregateRepository.cs | 0 .../Logo.png | Bin 13 files changed, 10 insertions(+), 10 deletions(-) rename src/{AggregateRepository.EventStore.Tests => AggregateRepository.Kurrent.Tests}/AggregateRepository.Kurrent.Tests.csproj (92%) rename src/{AggregateRepository.EventStore.Tests => AggregateRepository.Kurrent.Tests}/AggregateRepositoryTestFixture.cs (100%) rename src/{AggregateRepository.EventStore.Tests => AggregateRepository.Kurrent.Tests}/EventStoreAggregateRepositoryTests.cs (100%) rename src/{AggregateRepository.EventStore.Tests => AggregateRepository.Kurrent.Tests}/TestAggregate.cs (100%) rename src/{AggregateRepository.EventStore.Tests => AggregateRepository.Kurrent.Tests}/TestAggregateCreated.cs (100%) rename src/{AggregateRepository.EventStore.Tests => AggregateRepository.Kurrent.Tests}/TestEvent.cs (100%) rename src/{AggregateRepository.EventStore.Tests => AggregateRepository.Kurrent.Tests}/Usings.cs (100%) rename src/{AggregateRepository.EventStore => AggregateRepository.Kurrent}/AggregateRepository.Kurrent.csproj (96%) rename src/{AggregateRepository.EventStore => AggregateRepository.Kurrent}/KurrentDbAggregateRepository.cs (100%) rename src/{AggregateRepository.EventStore => AggregateRepository.Kurrent}/Logo.png (100%) diff --git a/build.cmd b/build.cmd index 0192423..f5462bc 100644 --- a/build.cmd +++ b/build.cmd @@ -8,9 +8,9 @@ IF NOT [%2]==[] (set TAG=%2) SET TAG=%TAG:tags/=% curl -o nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -.\\nuget.exe restore .\\src\\AggregateRepository.EventStore.Tests\\AggregateRepository.EventStore.Tests.csproj -PackagesDirectory .\\src\\packages -Verbosity detailed +.\\nuget.exe restore .\\src\\AggregateRepository.Kurrent.Tests\\AggregateRepository.Kurrent.Tests.csproj -PackagesDirectory .\\src\\packages -Verbosity detailed -dotnet test .\src\AggregateRepository.EventStore.Tests\AggregateRepository.EventStore.Tests.csproj +dotnet test .\src\AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj if %errorlevel% neq 0 exit /b %errorlevel% -dotnet pack .\src\AggregateRepository.EventStore\AggregateRepository.EventStore.csproj -o .\dist -p:Version="%VERSION%" -p:PackageVersion="%VERSION%" -p:Tag="%TAG%" -c Release \ No newline at end of file +dotnet pack .\src\AggregateRepository.Kurrent\AggregateRepository.Kurrent.csproj -o .\dist -p:Version="%VERSION%" -p:PackageVersion="%VERSION%" -p:Tag="%TAG%" -c Release \ No newline at end of file diff --git a/build.sh b/build.sh index cf0562d..6165f84 100755 --- a/build.sh +++ b/build.sh @@ -9,5 +9,5 @@ if [ -n "$2" ]; then tag="$2" fi tag=${tag/tags\//} -dotnet test .\\src\\AggregateRepository.EventStore.Tests\\AggregateRepository.EventStore.Tests.csproj -dotnet pack .\\src\\AggregateRepository.EventStore\\AggregateRepository.EventStore.csproj -o .\\dist -p:Version="$version" -p:PackageVersion="$version" -p:Tag="$tag" -c Release +dotnet test .\\src\\AggregateRepository.Kurrent.Tests\\AggregateRepository.Kurrent.Tests.csproj +dotnet pack .\\src\\AggregateRepository.Kurrent\\AggregateRepository.Kurrent.csproj -o .\\dist -p:Version="$version" -p:PackageVersion="$version" -p:Tag="$tag" -c Release diff --git a/src/AggregateRepository.EventStore.Tests/AggregateRepository.Kurrent.Tests.csproj b/src/AggregateRepository.Kurrent.Tests/AggregateRepository.Kurrent.Tests.csproj similarity index 92% rename from src/AggregateRepository.EventStore.Tests/AggregateRepository.Kurrent.Tests.csproj rename to src/AggregateRepository.Kurrent.Tests/AggregateRepository.Kurrent.Tests.csproj index 29e3ffb..190b039 100644 --- a/src/AggregateRepository.EventStore.Tests/AggregateRepository.Kurrent.Tests.csproj +++ b/src/AggregateRepository.Kurrent.Tests/AggregateRepository.Kurrent.Tests.csproj @@ -26,7 +26,7 @@ - + diff --git a/src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs b/src/AggregateRepository.Kurrent.Tests/AggregateRepositoryTestFixture.cs similarity index 100% rename from src/AggregateRepository.EventStore.Tests/AggregateRepositoryTestFixture.cs rename to src/AggregateRepository.Kurrent.Tests/AggregateRepositoryTestFixture.cs diff --git a/src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs b/src/AggregateRepository.Kurrent.Tests/EventStoreAggregateRepositoryTests.cs similarity index 100% rename from src/AggregateRepository.EventStore.Tests/EventStoreAggregateRepositoryTests.cs rename to src/AggregateRepository.Kurrent.Tests/EventStoreAggregateRepositoryTests.cs diff --git a/src/AggregateRepository.EventStore.Tests/TestAggregate.cs b/src/AggregateRepository.Kurrent.Tests/TestAggregate.cs similarity index 100% rename from src/AggregateRepository.EventStore.Tests/TestAggregate.cs rename to src/AggregateRepository.Kurrent.Tests/TestAggregate.cs diff --git a/src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs b/src/AggregateRepository.Kurrent.Tests/TestAggregateCreated.cs similarity index 100% rename from src/AggregateRepository.EventStore.Tests/TestAggregateCreated.cs rename to src/AggregateRepository.Kurrent.Tests/TestAggregateCreated.cs diff --git a/src/AggregateRepository.EventStore.Tests/TestEvent.cs b/src/AggregateRepository.Kurrent.Tests/TestEvent.cs similarity index 100% rename from src/AggregateRepository.EventStore.Tests/TestEvent.cs rename to src/AggregateRepository.Kurrent.Tests/TestEvent.cs diff --git a/src/AggregateRepository.EventStore.Tests/Usings.cs b/src/AggregateRepository.Kurrent.Tests/Usings.cs similarity index 100% rename from src/AggregateRepository.EventStore.Tests/Usings.cs rename to src/AggregateRepository.Kurrent.Tests/Usings.cs diff --git a/src/AggregateRepository.Kurrent.sln b/src/AggregateRepository.Kurrent.sln index f39fa1e..34a022b 100644 --- a/src/AggregateRepository.Kurrent.sln +++ b/src/AggregateRepository.Kurrent.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent", "AggregateRepository.EventStore\AggregateRepository.Kurrent.csproj", "{84A2B093-71F2-4015-94E1-5188AD8AEDF6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent", "AggregateRepository.Kurrent\AggregateRepository.Kurrent.csproj", "{84A2B093-71F2-4015-94E1-5188AD8AEDF6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent.Tests", "AggregateRepository.EventStore.Tests\AggregateRepository.Kurrent.Tests.csproj", "{5870B925-53E3-4B53-9975-46F508F11445}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent.Tests", "AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj", "{5870B925-53E3-4B53-9975-46F508F11445}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/AggregateRepository.EventStore/AggregateRepository.Kurrent.csproj b/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj similarity index 96% rename from src/AggregateRepository.EventStore/AggregateRepository.Kurrent.csproj rename to src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj index 292abf0..2a4e9f6 100644 --- a/src/AggregateRepository.EventStore/AggregateRepository.Kurrent.csproj +++ b/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj @@ -7,8 +7,8 @@ enable PharmaxoScientific.AggregateRepository.Kurrent PharmaxoScientific.AggregateRepository.Kurrent - Corsham Science - Corsham Science + Pharmaxo Scientific + Pharmaxo Scientific KurrentDB implementation for saving and rebuilding objects from event streams. PharmaxoScientific 2025 https://github.com/qphl/AggregateRepository.EventStore diff --git a/src/AggregateRepository.EventStore/KurrentDbAggregateRepository.cs b/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs similarity index 100% rename from src/AggregateRepository.EventStore/KurrentDbAggregateRepository.cs rename to src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs diff --git a/src/AggregateRepository.EventStore/Logo.png b/src/AggregateRepository.Kurrent/Logo.png similarity index 100% rename from src/AggregateRepository.EventStore/Logo.png rename to src/AggregateRepository.Kurrent/Logo.png From 3afba658839caa299b0c8cb08f0e5e172e0c4d71 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 13:51:45 +0100 Subject: [PATCH 07/21] Add dotnet format to build cmd --- build.cmd | 3 +++ build.sh | 1 + 2 files changed, 4 insertions(+) diff --git a/build.cmd b/build.cmd index f5462bc..7664ebe 100644 --- a/build.cmd +++ b/build.cmd @@ -10,6 +10,9 @@ SET TAG=%TAG:tags/=% curl -o nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe .\\nuget.exe restore .\\src\\AggregateRepository.Kurrent.Tests\\AggregateRepository.Kurrent.Tests.csproj -PackagesDirectory .\\src\\packages -Verbosity detailed +dotnet format .\src\AggregateRepository.Kurrent.sln --severity warn --verify-no-changes -v diag +if %errorlevel% neq 0 exit /b %errorlevel% + dotnet test .\src\AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj if %errorlevel% neq 0 exit /b %errorlevel% diff --git a/build.sh b/build.sh index 6165f84..ad30aff 100755 --- a/build.sh +++ b/build.sh @@ -9,5 +9,6 @@ if [ -n "$2" ]; then tag="$2" fi tag=${tag/tags\//} +dotnet format .\\src\\AggregateRepository.Kurrent.sln --severity warn --verify-no-changes -v diag dotnet test .\\src\\AggregateRepository.Kurrent.Tests\\AggregateRepository.Kurrent.Tests.csproj dotnet pack .\\src\\AggregateRepository.Kurrent\\AggregateRepository.Kurrent.csproj -o .\\dist -p:Version="$version" -p:PackageVersion="$version" -p:Tag="$tag" -c Release From bb439b0132937dabb508d38e360605ef5623ebdc Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 15:52:05 +0100 Subject: [PATCH 08/21] Updated test file name --- LICENSE | 2 +- ...eRepositoryTests.cs => KurrentDbAggregateRepositoryTests.cs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/AggregateRepository.Kurrent.Tests/{EventStoreAggregateRepositoryTests.cs => KurrentDbAggregateRepositoryTests.cs} (100%) diff --git a/LICENSE b/LICENSE index 3c50500..3586193 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013, Cognisant Research +Copyright (c) 2025, Pharmaxo Scientific All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/src/AggregateRepository.Kurrent.Tests/EventStoreAggregateRepositoryTests.cs b/src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs similarity index 100% rename from src/AggregateRepository.Kurrent.Tests/EventStoreAggregateRepositoryTests.cs rename to src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs From 1cdf05536003f7be0a8a5caef6563bb2e3615df1 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 15:55:50 +0100 Subject: [PATCH 09/21] Added back ghcr.io to check if reason for failing tests --- .../KurrentDbAggregateRepositoryTests.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs b/src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs index 31ddfe5..569741a 100644 --- a/src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs +++ b/src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs @@ -18,12 +18,10 @@ protected override async Task InitRepository() { const string eventStoreVersion = "24.10.5"; - // If on arm (like an m1 mac) use the alpha arm image from github - var architectureSuffix = RuntimeInformation.OSArchitecture == Architecture.Arm64 - ? "-alpha-arm64v8" - : "-bookworm-slim"; - - var imageName = $"eventstore/eventstore:{eventStoreVersion}{architectureSuffix}"; + var imageName = RuntimeInformation.OSArchitecture == Architecture.Arm64 + // if on arm (like an m1 mac) use the alpha arm image from github + ? $"ghcr.io/eventstore/eventstore:{eventStoreVersion}-alpha-arm64v8" + : $"eventstore/eventstore:{eventStoreVersion}-bookworm-slim"; const int hostPort = 2113; From 790dd2fcfa830448a1769fbd06e734ce684f2b91 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 16:36:39 +0100 Subject: [PATCH 10/21] Basic readme update + dotnet restore solution --- README.md | 6 +++--- build.cmd | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 88cb901..e597001 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -cr-aggregaterepository +Pharmaxo Scientific Aggregate Repository ====================== -Common library for saving and rebuilding of objects from event streams - Includes JOliver, GetEventStore and InMemory Implementations +Common library for saving and rebuilding of objects from Kurrent DB event streams using KurrentDBClient. -[![cognisant-libs MyGet Build Status](https://www.myget.org/BuildSource/Badge/cognisant-libs?identifier=a31a1e31-93c4-4e75-8491-957e0983949f)](https://www.myget.org/) +[Pharmaxo Scientific Aggregate Repository](https://www.nuget.org/packages/CorshamScience.AggregateRepository.EventStore) diff --git a/build.cmd b/build.cmd index 7664ebe..3949ec1 100644 --- a/build.cmd +++ b/build.cmd @@ -7,8 +7,7 @@ SET TAG=0.0.0 IF NOT [%2]==[] (set TAG=%2) SET TAG=%TAG:tags/=% -curl -o nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -.\\nuget.exe restore .\\src\\AggregateRepository.Kurrent.Tests\\AggregateRepository.Kurrent.Tests.csproj -PackagesDirectory .\\src\\packages -Verbosity detailed +dotnet restore .\src\AggregateRepository.Kurrent.sln -PackagesDirectory .\src\packages -Verbosity detailed dotnet format .\src\AggregateRepository.Kurrent.sln --severity warn --verify-no-changes -v diag if %errorlevel% neq 0 exit /b %errorlevel% From 7bb3514af1e686c33723a43e427a923e540e70e9 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Tue, 27 May 2025 17:30:04 +0100 Subject: [PATCH 11/21] Revert change to expectedVersion logic --- .../KurrentDbAggregateRepository.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs b/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs index 9e11617..41458b4 100644 --- a/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs +++ b/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs @@ -33,8 +33,8 @@ public async Task SaveAsync(IAggregate aggregateToSave) var streamName = StreamNameForAggregateId(aggregateToSave.Id); var originalVersion = aggregateToSave.Version - events.Count; - var expectedVersion = originalVersion == 0 ? StreamState.NoStream : StreamState.StreamRevision((ulong)originalVersion - 1); - + var expectedVersion = originalVersion == 0 ? StreamState.NoStream : (ulong)(originalVersion - 1); + var preparedEvents = events .Select(ToEventData) .ToArray(); From 6b991d436716c60902b02ebc24e68ee99c7572bf Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 09:59:34 +0100 Subject: [PATCH 12/21] target net481 --- .../AggregateRepository.Kurrent.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj b/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj index 2a4e9f6..3a7fb30 100644 --- a/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj +++ b/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj @@ -1,7 +1,7 @@  - net8.0;net48 + net8.0;net481 latest enable enable From 12819a71dd81e061f0c052b0a14b8e1f58e73096 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 10:23:13 +0100 Subject: [PATCH 13/21] Try to fail build --- build.cmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.cmd b/build.cmd index 3949ec1..a479a5e 100644 --- a/build.cmd +++ b/build.cmd @@ -10,9 +10,9 @@ SET TAG=%TAG:tags/=% dotnet restore .\src\AggregateRepository.Kurrent.sln -PackagesDirectory .\src\packages -Verbosity detailed dotnet format .\src\AggregateRepository.Kurrent.sln --severity warn --verify-no-changes -v diag -if %errorlevel% neq 0 exit /b %errorlevel% +if %errorlevel% neq 0 exit %errorlevel% dotnet test .\src\AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj -if %errorlevel% neq 0 exit /b %errorlevel% +if %errorlevel% neq 0 exit %errorlevel% dotnet pack .\src\AggregateRepository.Kurrent\AggregateRepository.Kurrent.csproj -o .\dist -p:Version="%VERSION%" -p:PackageVersion="%VERSION%" -p:Tag="%TAG%" -c Release \ No newline at end of file From 1e8fb2c02bf5ee02ed4cfe61af6aadbd51f162fb Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 10:38:48 +0100 Subject: [PATCH 14/21] formatting --- src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs b/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs index 41458b4..0700ffb 100644 --- a/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs +++ b/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs @@ -34,7 +34,7 @@ public async Task SaveAsync(IAggregate aggregateToSave) var originalVersion = aggregateToSave.Version - events.Count; var expectedVersion = originalVersion == 0 ? StreamState.NoStream : (ulong)(originalVersion - 1); - + var preparedEvents = events .Select(ToEventData) .ToArray(); From 3ab34e91ae78ddbfe225d541417d0c7ba2554fa8 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 11:37:23 +0100 Subject: [PATCH 15/21] Optional flag to disable tests --- build.cmd | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/build.cmd b/build.cmd index a479a5e..2df6723 100644 --- a/build.cmd +++ b/build.cmd @@ -1,18 +1,25 @@ @echo off SET VERSION=0.0.0 -IF NOT [%1]==[] (set VERSION=%1) +IF NOT [%1]==[] (SET VERSION=%1) SET TAG=0.0.0 -IF NOT [%2]==[] (set TAG=%2) +IF NOT [%2]==[] (SET TAG=%2) SET TAG=%TAG:tags/=% +SET RUNTESTS=true +IF NOT [%3]==[] (SET RUNTESTS=%3) + dotnet restore .\src\AggregateRepository.Kurrent.sln -PackagesDirectory .\src\packages -Verbosity detailed dotnet format .\src\AggregateRepository.Kurrent.sln --severity warn --verify-no-changes -v diag -if %errorlevel% neq 0 exit %errorlevel% +IF %errorlevel% neq 0 EXIT /B %errorlevel% -dotnet test .\src\AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj -if %errorlevel% neq 0 exit %errorlevel% +IF /I "%RUNTESTS%"=="true" ( + dotnet test .\src\AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj + IF %errorlevel% neq 0 EXIT /B %errorlevel% +) ELSE ( + ECHO Skipping tests because RUNTESTS is not set to "true". +) dotnet pack .\src\AggregateRepository.Kurrent\AggregateRepository.Kurrent.csproj -o .\dist -p:Version="%VERSION%" -p:PackageVersion="%VERSION%" -p:Tag="%TAG%" -c Release \ No newline at end of file From b330b17fe65eb4ffea8a5394664dca64a8991d5c Mon Sep 17 00:00:00 2001 From: JoshPattie <112478822+JoshPattie@users.noreply.github.com> Date: Wed, 28 May 2025 11:42:13 +0100 Subject: [PATCH 16/21] Update src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj Co-authored-by: Sam Matthews <36134497+SamBucaMatthews@users.noreply.github.com> --- .../AggregateRepository.Kurrent.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj b/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj index 3a7fb30..3035267 100644 --- a/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj +++ b/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj @@ -10,7 +10,7 @@ Pharmaxo Scientific Pharmaxo Scientific KurrentDB implementation for saving and rebuilding objects from event streams. - PharmaxoScientific 2025 + Pharmaxo Scientific 2025 https://github.com/qphl/AggregateRepository.EventStore https://github.com/qphl/AggregateRepository.EventStore https://raw.githubusercontent.com/qphl/AggregateRepository.EventStore/master/logo.png From d0980d32b890aae3ab6c245810f700c4157e9e67 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 12:10:28 +0100 Subject: [PATCH 17/21] Renamed Kurrent to KurrentDB --- .../AggregateRepository.KurrentDB.Tests.csproj} | 2 +- .../AggregateRepositoryTestFixture.cs | 2 +- .../KurrentDbAggregateRepositoryTests.cs | 4 ++-- .../TestAggregate.cs | 2 +- .../TestAggregateCreated.cs | 2 +- .../TestEvent.cs | 2 +- .../Usings.cs | 0 ...urrent.sln => AggregateRepository.KurrentDB.sln} | 4 ++-- .../AggregateRepository.KurrentDB.csproj} | 10 +++++----- .../KurrentDbAggregateRepository.cs | 2 +- .../Logo.png | Bin 11 files changed, 15 insertions(+), 15 deletions(-) rename src/{AggregateRepository.Kurrent.Tests/AggregateRepository.Kurrent.Tests.csproj => AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj} (92%) rename src/{AggregateRepository.Kurrent.Tests => AggregateRepository.KurrentDB.Tests}/AggregateRepositoryTestFixture.cs (99%) rename src/{AggregateRepository.Kurrent.Tests => AggregateRepository.KurrentDB.Tests}/KurrentDbAggregateRepositoryTests.cs (94%) rename src/{AggregateRepository.Kurrent.Tests => AggregateRepository.KurrentDB.Tests}/TestAggregate.cs (95%) rename src/{AggregateRepository.Kurrent.Tests => AggregateRepository.KurrentDB.Tests}/TestAggregateCreated.cs (82%) rename src/{AggregateRepository.Kurrent.Tests => AggregateRepository.KurrentDB.Tests}/TestEvent.cs (78%) rename src/{AggregateRepository.Kurrent.Tests => AggregateRepository.KurrentDB.Tests}/Usings.cs (100%) rename src/{AggregateRepository.Kurrent.sln => AggregateRepository.KurrentDB.sln} (83%) rename src/{AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj => AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj} (87%) rename src/{AggregateRepository.Kurrent => AggregateRepository.KurrentDB}/KurrentDbAggregateRepository.cs (98%) rename src/{AggregateRepository.Kurrent => AggregateRepository.KurrentDB}/Logo.png (100%) diff --git a/src/AggregateRepository.Kurrent.Tests/AggregateRepository.Kurrent.Tests.csproj b/src/AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj similarity index 92% rename from src/AggregateRepository.Kurrent.Tests/AggregateRepository.Kurrent.Tests.csproj rename to src/AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj index 190b039..450ae59 100644 --- a/src/AggregateRepository.Kurrent.Tests/AggregateRepository.Kurrent.Tests.csproj +++ b/src/AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj @@ -26,7 +26,7 @@ - + diff --git a/src/AggregateRepository.Kurrent.Tests/AggregateRepositoryTestFixture.cs b/src/AggregateRepository.KurrentDB.Tests/AggregateRepositoryTestFixture.cs similarity index 99% rename from src/AggregateRepository.Kurrent.Tests/AggregateRepositoryTestFixture.cs rename to src/AggregateRepository.KurrentDB.Tests/AggregateRepositoryTestFixture.cs index ab3ba55..667ffdf 100644 --- a/src/AggregateRepository.Kurrent.Tests/AggregateRepositoryTestFixture.cs +++ b/src/AggregateRepository.KurrentDB.Tests/AggregateRepositoryTestFixture.cs @@ -3,7 +3,7 @@ using CorshamScience.AggregateRepository.Core; using CorshamScience.AggregateRepository.Core.Exceptions; -namespace AggregateRepository.Kurrent.Tests; +namespace AggregateRepository.KurrentDB.Tests; [TestFixture] public abstract class AggregateRepositoryTestFixture diff --git a/src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs b/src/AggregateRepository.KurrentDB.Tests/KurrentDbAggregateRepositoryTests.cs similarity index 94% rename from src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs rename to src/AggregateRepository.KurrentDB.Tests/KurrentDbAggregateRepositoryTests.cs index 569741a..1e6d88e 100644 --- a/src/AggregateRepository.Kurrent.Tests/KurrentDbAggregateRepositoryTests.cs +++ b/src/AggregateRepository.KurrentDB.Tests/KurrentDbAggregateRepositoryTests.cs @@ -5,9 +5,9 @@ using DotNet.Testcontainers.Containers; using DotNet.Testcontainers.Images; using KurrentDB.Client; -using PharmaxoScientific.AggregateRepository.Kurrent; +using PharmaxoScientific.AggregateRepository.KurrentDB; -namespace AggregateRepository.Kurrent.Tests; +namespace AggregateRepository.KurrentDB.Tests; internal class KurrentDbAggregateRepositoryTests : AggregateRepositoryTestFixture { diff --git a/src/AggregateRepository.Kurrent.Tests/TestAggregate.cs b/src/AggregateRepository.KurrentDB.Tests/TestAggregate.cs similarity index 95% rename from src/AggregateRepository.Kurrent.Tests/TestAggregate.cs rename to src/AggregateRepository.KurrentDB.Tests/TestAggregate.cs index 8156ecc..e49c75d 100644 --- a/src/AggregateRepository.Kurrent.Tests/TestAggregate.cs +++ b/src/AggregateRepository.KurrentDB.Tests/TestAggregate.cs @@ -2,7 +2,7 @@ using CorshamScience.AggregateRepository.Core; -namespace AggregateRepository.Kurrent.Tests; +namespace AggregateRepository.KurrentDB.Tests; internal sealed class TestAggregate : AggregateBase { diff --git a/src/AggregateRepository.Kurrent.Tests/TestAggregateCreated.cs b/src/AggregateRepository.KurrentDB.Tests/TestAggregateCreated.cs similarity index 82% rename from src/AggregateRepository.Kurrent.Tests/TestAggregateCreated.cs rename to src/AggregateRepository.KurrentDB.Tests/TestAggregateCreated.cs index f856f3b..809daa1 100644 --- a/src/AggregateRepository.Kurrent.Tests/TestAggregateCreated.cs +++ b/src/AggregateRepository.KurrentDB.Tests/TestAggregateCreated.cs @@ -1,6 +1,6 @@ // Copyright (c) Pharmaxo. All rights reserved. -namespace AggregateRepository.Kurrent.Tests; +namespace AggregateRepository.KurrentDB.Tests; internal class TestAggregateCreated { diff --git a/src/AggregateRepository.Kurrent.Tests/TestEvent.cs b/src/AggregateRepository.KurrentDB.Tests/TestEvent.cs similarity index 78% rename from src/AggregateRepository.Kurrent.Tests/TestEvent.cs rename to src/AggregateRepository.KurrentDB.Tests/TestEvent.cs index 672e0f2..890be5d 100644 --- a/src/AggregateRepository.Kurrent.Tests/TestEvent.cs +++ b/src/AggregateRepository.KurrentDB.Tests/TestEvent.cs @@ -1,6 +1,6 @@ // Copyright (c) Pharmaxo. All rights reserved. -namespace AggregateRepository.Kurrent.Tests; +namespace AggregateRepository.KurrentDB.Tests; internal class TestEvent { diff --git a/src/AggregateRepository.Kurrent.Tests/Usings.cs b/src/AggregateRepository.KurrentDB.Tests/Usings.cs similarity index 100% rename from src/AggregateRepository.Kurrent.Tests/Usings.cs rename to src/AggregateRepository.KurrentDB.Tests/Usings.cs diff --git a/src/AggregateRepository.Kurrent.sln b/src/AggregateRepository.KurrentDB.sln similarity index 83% rename from src/AggregateRepository.Kurrent.sln rename to src/AggregateRepository.KurrentDB.sln index 34a022b..464d05e 100644 --- a/src/AggregateRepository.Kurrent.sln +++ b/src/AggregateRepository.KurrentDB.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent", "AggregateRepository.Kurrent\AggregateRepository.Kurrent.csproj", "{84A2B093-71F2-4015-94E1-5188AD8AEDF6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.KurrentDB", "AggregateRepository.KurrentDB\AggregateRepository.KurrentDB.csproj", "{84A2B093-71F2-4015-94E1-5188AD8AEDF6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.Kurrent.Tests", "AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj", "{5870B925-53E3-4B53-9975-46F508F11445}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateRepository.KurrentDB.Tests", "AggregateRepository.KurrentDB.Tests\AggregateRepository.KurrentDB.Tests.csproj", "{5870B925-53E3-4B53-9975-46F508F11445}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj b/src/AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj similarity index 87% rename from src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj rename to src/AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj index 3035267..7d30fee 100644 --- a/src/AggregateRepository.Kurrent/AggregateRepository.Kurrent.csproj +++ b/src/AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj @@ -5,8 +5,8 @@ latest enable enable - PharmaxoScientific.AggregateRepository.Kurrent - PharmaxoScientific.AggregateRepository.Kurrent + PharmaxoScientific.AggregateRepository.KurrentDB + PharmaxoScientific.AggregateRepository.KurrentDB Pharmaxo Scientific Pharmaxo Scientific KurrentDB implementation for saving and rebuilding objects from event streams. @@ -15,15 +15,15 @@ https://github.com/qphl/AggregateRepository.EventStore https://raw.githubusercontent.com/qphl/AggregateRepository.EventStore/master/logo.png Event Store, KurrentDB, Event Sourcing, Aggregate Repository - PharmaxoScientific.AggregateRepository + PharmaxoScientific.AggregateRepository.KurrentDB https://GitHub.com/qphl/AggregateRepository.EventStore/releases/tag/ - PharmaxoScientific.AggregateRepository.Kurrent + PharmaxoScientific.AggregateRepository.KurrentDB BSD-3-Clause Logo.png - bin\Debug\netstandard2.0\CorshamScience.AggregateRepository.EventStore.xml + diff --git a/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs b/src/AggregateRepository.KurrentDB/KurrentDbAggregateRepository.cs similarity index 98% rename from src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs rename to src/AggregateRepository.KurrentDB/KurrentDbAggregateRepository.cs index 0700ffb..4dfe0d6 100644 --- a/src/AggregateRepository.Kurrent/KurrentDbAggregateRepository.cs +++ b/src/AggregateRepository.KurrentDB/KurrentDbAggregateRepository.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace PharmaxoScientific.AggregateRepository.Kurrent; +namespace PharmaxoScientific.AggregateRepository.KurrentDB; /// /// diff --git a/src/AggregateRepository.Kurrent/Logo.png b/src/AggregateRepository.KurrentDB/Logo.png similarity index 100% rename from src/AggregateRepository.Kurrent/Logo.png rename to src/AggregateRepository.KurrentDB/Logo.png From 3a96885bec61a7f1194efcd8afdb30bbed2ae543 Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 12:14:22 +0100 Subject: [PATCH 18/21] Fixed missing rename in build script + removed unused script --- build.cmd | 8 ++++---- build.sh | 14 -------------- 2 files changed, 4 insertions(+), 18 deletions(-) delete mode 100755 build.sh diff --git a/build.cmd b/build.cmd index 2df6723..4b20564 100644 --- a/build.cmd +++ b/build.cmd @@ -10,16 +10,16 @@ SET TAG=%TAG:tags/=% SET RUNTESTS=true IF NOT [%3]==[] (SET RUNTESTS=%3) -dotnet restore .\src\AggregateRepository.Kurrent.sln -PackagesDirectory .\src\packages -Verbosity detailed +dotnet restore .\src\AggregateRepository.KurrentDB.sln -PackagesDirectory .\src\packages -Verbosity detailed -dotnet format .\src\AggregateRepository.Kurrent.sln --severity warn --verify-no-changes -v diag +dotnet format .\src\AggregateRepository.KurrentDB.sln --severity warn --verify-no-changes -v diag IF %errorlevel% neq 0 EXIT /B %errorlevel% IF /I "%RUNTESTS%"=="true" ( - dotnet test .\src\AggregateRepository.Kurrent.Tests\AggregateRepository.Kurrent.Tests.csproj + dotnet test .\src\AggregateRepository.KurrentDB.Tests\AggregateRepository.KurrentDB.Tests.csproj IF %errorlevel% neq 0 EXIT /B %errorlevel% ) ELSE ( ECHO Skipping tests because RUNTESTS is not set to "true". ) -dotnet pack .\src\AggregateRepository.Kurrent\AggregateRepository.Kurrent.csproj -o .\dist -p:Version="%VERSION%" -p:PackageVersion="%VERSION%" -p:Tag="%TAG%" -c Release \ No newline at end of file +dotnet pack .\src\AggregateRepository.KurrentDB\AggregateRepository.KurrentDB.csproj -o .\dist -p:Version="%VERSION%" -p:PackageVersion="%VERSION%" -p:Tag="%TAG%" -c Release \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100755 index ad30aff..0000000 --- a/build.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -e -version="0.0.0" -if [ -n "$1" ]; then version="$1" -fi - -tag="0.0.0" -if [ -n "$2" ]; then tag="$2" -fi -tag=${tag/tags\//} - -dotnet format .\\src\\AggregateRepository.Kurrent.sln --severity warn --verify-no-changes -v diag -dotnet test .\\src\\AggregateRepository.Kurrent.Tests\\AggregateRepository.Kurrent.Tests.csproj -dotnet pack .\\src\\AggregateRepository.Kurrent\\AggregateRepository.Kurrent.csproj -o .\\dist -p:Version="$version" -p:PackageVersion="$version" -p:Tag="$tag" -c Release From 4bcdd1379881894805a575206a17844abc7a61fe Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 12:24:55 +0100 Subject: [PATCH 19/21] Updated references to the repository --- README.md | 4 ++-- .../AggregateRepository.KurrentDB.csproj | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e597001..d85c88d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Pharmaxo Scientific Aggregate Repository ====================== -Common library for saving and rebuilding of objects from Kurrent DB event streams using KurrentDBClient. +Common library for saving and rebuilding of objects from Kurrent DB event streams using the KurrentDBClient. -[Pharmaxo Scientific Aggregate Repository](https://www.nuget.org/packages/CorshamScience.AggregateRepository.EventStore) +[Pharmaxo Scientific Aggregate Repository](https://www.nuget.org/packages/PharmaxoScientific.AggregateRepository.KurrentDB) diff --git a/src/AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj b/src/AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj index 7d30fee..3427345 100644 --- a/src/AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj +++ b/src/AggregateRepository.KurrentDB/AggregateRepository.KurrentDB.csproj @@ -11,25 +11,25 @@ Pharmaxo Scientific KurrentDB implementation for saving and rebuilding objects from event streams. Pharmaxo Scientific 2025 - https://github.com/qphl/AggregateRepository.EventStore - https://github.com/qphl/AggregateRepository.EventStore - https://raw.githubusercontent.com/qphl/AggregateRepository.EventStore/master/logo.png + https://github.com/qphl/AggregateRepository.KurrentDB + https://github.com/qphl/AggregateRepository.KurrentDB + https://raw.githubusercontent.com/qphl/AggregateRepository.KurrentDB/master/logo.png Event Store, KurrentDB, Event Sourcing, Aggregate Repository PharmaxoScientific.AggregateRepository.KurrentDB - https://GitHub.com/qphl/AggregateRepository.EventStore/releases/tag/ + https://GitHub.com/qphl/AggregateRepository.KurrentDB/releases/tag/ PharmaxoScientific.AggregateRepository.KurrentDB BSD-3-Clause Logo.png - + bin\Debug\net8.0\PharmaxoScientific.AggregateRepository.KurrentDB.xml true - bin\Release\netstandard2.0\CorshamScience.AggregateRepository.Persistence.EventStore.xml + bin\Release\net8.0\PharmaxoScientific.AggregateRepository.KurrentDB.xml From 0c1eeb07d02c7b56a4e36bec1f0f35ec12040b2c Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Wed, 28 May 2025 15:07:38 +0100 Subject: [PATCH 20/21] Updated missing reference in License --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 3586193..855d86f 100644 --- a/LICENSE +++ b/LICENSE @@ -5,5 +5,5 @@ Redistribution and use in source and binary forms, with or without modification, Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -Neither the name of Cognisant Research nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +Neither the name of Pharmaxo Scientific nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file From 5df83c8243dab8b50ce2559f75a9f1c0c6bad6cb Mon Sep 17 00:00:00 2001 From: Josh Pattie Date: Thu, 5 Jun 2025 11:11:17 +0100 Subject: [PATCH 21/21] Updated tests to target 481 + ES now runs as developer mode --- .../AggregateRepository.KurrentDB.Tests.csproj | 4 ++-- .../KurrentDbAggregateRepositoryTests.cs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj b/src/AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj index 450ae59..7ecebba 100644 --- a/src/AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj +++ b/src/AggregateRepository.KurrentDB.Tests/AggregateRepository.KurrentDB.Tests.csproj @@ -1,10 +1,10 @@  - net8.0 + net8.0;net481 + latest enable enable - false diff --git a/src/AggregateRepository.KurrentDB.Tests/KurrentDbAggregateRepositoryTests.cs b/src/AggregateRepository.KurrentDB.Tests/KurrentDbAggregateRepositoryTests.cs index 1e6d88e..05415db 100644 --- a/src/AggregateRepository.KurrentDB.Tests/KurrentDbAggregateRepositoryTests.cs +++ b/src/AggregateRepository.KurrentDB.Tests/KurrentDbAggregateRepositoryTests.cs @@ -29,9 +29,11 @@ protected override async Task InitRepository() .WithImage(new DockerImage(imageName)) .WithCleanUp(true) .WithPortBinding(hostPort) + .WithCreateParameterModifier(cmd => cmd.User = "root") .WithEnvironment(new Dictionary { - { "EVENTSTORE_INSECURE", "true" }, + { "EVENTSTORE_INSECURE", "false" }, + { "EVENTSTORE_DEV", "true" }, { "EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "true" }, }) .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(hostPort)) @@ -40,7 +42,7 @@ protected override async Task InitRepository() await _container.StartAsync(); var settings = KurrentDBClientSettings - .Create($"esdb://admin:changeit@127.0.0.1:{hostPort}?tls=false"); + .Create($"esdb://admin:changeit@127.0.0.1:{hostPort}?tls=true&tlsVerifyCert=false"); _client = new KurrentDBClient(settings); RepoUnderTest = new KurrentDbAggregateRepository(_client);