diff --git a/src/Benchmark/Benchmark.csproj b/src/Benchmark/Benchmark.csproj
index 64b91b8..00731c2 100644
--- a/src/Benchmark/Benchmark.csproj
+++ b/src/Benchmark/Benchmark.csproj
@@ -2,14 +2,15 @@
Exe
- net6.0
+ net6.0;net7.0;net8.0;net9.0;net10.0
+ latest
enable
disable
-
-
+
+
diff --git a/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient.csproj b/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient.csproj
index 57f1cd2..918f62e 100644
--- a/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient.csproj
+++ b/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient.csproj
@@ -2,14 +2,16 @@
Exe
- net6.0
+ net6.0;net7.0;net8.0;net9.0;net10.0
+ latest
-
-
-
-
+
+
+
+
+
diff --git a/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/Program.cs b/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/Program.cs
index db30cb8..300531c 100644
--- a/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/Program.cs
+++ b/src/BullOak.Repositories.EventStore.ConsoleTestEventStoreClient/Program.cs
@@ -1,12 +1,9 @@
using System;
-using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
-using System.Text.Json.Serialization;
using System.Threading.Tasks;
using EventStore.Client;
-using EventStore.Client.Projections;
namespace BullOak.Repositories.EventStore.ConsoleTestEventStoreClient
{
@@ -65,7 +62,7 @@ static async Task Main(string[] args)
var isSuccess = await readResult.ReadState;
var events = await readResult.Where(x=> x.Event != null).ToListAsync();
-
+
var eventCount = events.Count;
var readResultStream = client.ReadStreamAsync(Direction.Forwards, "dokimi-2", StreamPosition.Start);
@@ -107,4 +104,4 @@ await client.AppendToStreamAsync(idForTombstoneTest, StreamRevision.FromInt64(-1
// Softdeleted streams write with expected stream revision -1
// Categories throw if tried to read when they are empty
// Categories only get created and populated with data writter AFTER they're created
-// Tombstoned
+// Tombstoned
diff --git a/src/BullOak.Repositories.EventStore.Test.Integration/BullOak.Repositories.EventStore.Test.Integration.csproj b/src/BullOak.Repositories.EventStore.Test.Integration/BullOak.Repositories.EventStore.Test.Integration.csproj
index 3a7adde..9f9a3e6 100644
--- a/src/BullOak.Repositories.EventStore.Test.Integration/BullOak.Repositories.EventStore.Test.Integration.csproj
+++ b/src/BullOak.Repositories.EventStore.Test.Integration/BullOak.Repositories.EventStore.Test.Integration.csproj
@@ -1,8 +1,8 @@
- net6.0
- 9.0
+ net6.0;net7.0;net8.0;net9.0;net10.0
+ latest
false
true
true
@@ -11,26 +11,17 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
+
+
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/BullOak.Repositories.EventStore.Test.Integration/Contexts/EventStoreIntegrationContext.cs b/src/BullOak.Repositories.EventStore.Test.Integration/Contexts/EventStoreIntegrationContext.cs
index e071356..0a02d4a 100644
--- a/src/BullOak.Repositories.EventStore.Test.Integration/Contexts/EventStoreIntegrationContext.cs
+++ b/src/BullOak.Repositories.EventStore.Test.Integration/Contexts/EventStoreIntegrationContext.cs
@@ -1,5 +1,6 @@
-namespace BullOak.Repositories.EventStore.Test.Integration.Contexts
-{
+using EventStore.Client;
+
+namespace BullOak.Repositories.EventStore.Test.Integration.Contexts {
using Config;
using Components;
using Session;
@@ -10,12 +11,9 @@
using System.Reflection;
using System.Threading.Tasks;
using Events;
- using ClientV5 = global::EventStore.ClientAPI;
- using ClientV20 = global::EventStore.Client;
using Streams;
- internal class EventStoreIntegrationContext : IDisposable
- {
+ internal class EventStoreIntegrationContext {
private readonly PassThroughValidator validator;
private static IHoldAllConfiguration configuration;
@@ -23,53 +21,46 @@ internal class EventStoreIntegrationContext : IDisposable
public IReadEventsFromStream EventReader { get; private set; }
private EventStoreRepository repository;
- private EventStoreRepository Repository
- {
- get
- {
+
+ private EventStoreRepository Repository {
+ get {
if (repository == null)
BuildRepositories().Wait();
return repository;
}
}
- public EventStoreReadOnlyRepository ReadOnlyRepository
- {
- get
- {
+
+ public EventStoreReadOnlyRepository ReadOnlyRepository {
+ get {
if (readOnlyRepository == null)
BuildRepositories().Wait();
return readOnlyRepository;
}
}
- public async Task BuildRepositories(Protocol chosenProtocol = Protocol.Tcp)
- {
- protocol = chosenProtocol;
+ public async Task BuildRepositories() {
EventReader = await ConfigureReader();
EventWriter = await ConfigureWriter();
- repository = new EventStoreRepository(validator, configuration, EventReader, EventWriter, DateTimeProvider);
+ repository = new EventStoreRepository(validator, configuration, EventReader,
+ EventWriter, DateTimeProvider);
readOnlyRepository = new EventStoreReadOnlyRepository(configuration, EventReader);
}
- private Protocol protocol;
- private ClientV5.IEventStoreConnection connV5;
- private ClientV20.EventStoreClient connV20;
+ private EventStoreClient connV20;
private EventStoreReadOnlyRepository readOnlyRepository;
public TestDateTimeProvider DateTimeProvider { get; }
- public EventStoreIntegrationContext(PassThroughValidator validator)
- {
+ public EventStoreIntegrationContext(PassThroughValidator validator) {
this.validator = validator;
DateTimeProvider = new TestDateTimeProvider();
}
- public static void SetupNode()
- {
+ public static void SetupNode() {
configuration = Configuration.Begin()
.WithDefaultCollection()
.WithDefaultStateFactory()
@@ -82,45 +73,32 @@ public static void SetupNode()
}
async Task ConfigureReader()
- => protocol switch
- {
- Protocol.Tcp => new TcpEventReader(await ConfigureEventStoreTcp(), configuration),
- Protocol.Grpc => new GrpcEventReader(await ConfigureEventStoreGrpc(), configuration),
- _ => throw new ArgumentOutOfRangeException(nameof(protocol))
- };
+ => new GrpcEventReader(await ConfigureEventStoreGrpc(), configuration);
async Task ConfigureWriter()
- => protocol switch
- {
- Protocol.Tcp => new TcpEventWriter(await ConfigureEventStoreTcp()),
- Protocol.Grpc => new GrpcEventWriter(await ConfigureEventStoreGrpc()),
- _ => throw new ArgumentOutOfRangeException(nameof(protocol))
- };
-
- public static void TeardownNode()
- {
- }
+ => new GrpcEventWriter(await ConfigureEventStoreGrpc());
+
+ public static void TeardownNode() { }
- public async Task> StartSession(string streamName, DateTime? appliesAt = null, bool optimizeForShortStreams = true)
- {
- var session = await Repository.BeginSessionFor(streamName, appliesAt: appliesAt, optimization: optimizeForShortStreams ? OptimizeFor.ShortStreams : OptimizeFor.LongStreams).ConfigureAwait(false);
+ public async Task> StartSession(string streamName,
+ DateTime? appliesAt = null, bool optimizeForShortStreams = true) {
+ var session = await Repository.BeginSessionFor(streamName, appliesAt: appliesAt,
+ optimization: optimizeForShortStreams ? OptimizeFor.ShortStreams : OptimizeFor.LongStreams)
+ .ConfigureAwait(false);
return session;
}
- public async Task>> ReadAllEntitiesFromCategory(string categoryName, DateTime? appliesAt = null)
- {
- return await ReadOnlyRepository.ReadAllEntitiesFromCategory(categoryName, e =>
- {
+ public async Task>> ReadAllEntitiesFromCategory(string categoryName,
+ DateTime? appliesAt = null) {
+ return await ReadOnlyRepository.ReadAllEntitiesFromCategory(categoryName, e => {
if (!appliesAt.HasValue || e.Metadata?.Properties == null) return true;
return e.Metadata.TimeStamp <= appliesAt;
}).ConfigureAwait(false);
}
- public async Task AppendEventsToCurrentStream(string id, IMyEvent[] events)
- {
- using (var session = await StartSession(id))
- {
+ public async Task AppendEventsToCurrentStream(string id, IMyEvent[] events) {
+ using (var session = await StartSession(id)) {
session.AddEvents(events);
await session.SaveChanges();
}
@@ -131,116 +109,47 @@ public Task SoftDeleteStream(string id)
public Task HardDeleteStream(string id)
- => protocol switch
- {
- Protocol.Tcp => connV5.DeleteStreamAsync(id, -1, true),
- Protocol.Grpc => connV20.TombstoneAsync(id, ClientV20.StreamState.Any),
- _ => throw new ArgumentOutOfRangeException(nameof(protocol))
- };
+ => connV20.TombstoneAsync(id,StreamState.Any);
public Task ReadEventsFromStreamRaw(string id)
- => protocol switch
- {
- Protocol.Tcp => TcpReadEventsFromStreamRaw(id),
- Protocol.Grpc => GrpcReadEventsFromStreamRaw(id),
- _ => throw new ArgumentOutOfRangeException(nameof(protocol))
- };
-
- private async Task GrpcReadEventsFromStreamRaw(string id)
- {
- var readResults = connV20.ReadStreamAsync(ClientV20.Direction.Forwards, id, ClientV20.StreamPosition.Start);
- return await readResults
- .Where(e => e.Event != null)
- .Select(e => e.Event.ToStoredEvent(configuration.StateFactory))
- .ToArrayAsync();
- }
+ => GrpcReadEventsFromStreamRaw(id);
- private async Task TcpReadEventsFromStreamRaw(string id)
- {
- var result = new List();
- ClientV5.StreamEventsSlice currentSlice;
- long nextSliceStart = ClientV5.StreamPosition.Start;
- do
- {
- currentSlice = await connV5.ReadStreamEventsForwardAsync(id, nextSliceStart, 100, false);
- nextSliceStart = currentSlice.NextEventNumber;
- result.AddRange(currentSlice.Events);
- } while (!currentSlice.IsEndOfStream);
-
- return result
- .Where(e => e.Event != null)
- .Select((e, _) => e.Event.ToStoredEvent(configuration.StateFactory))
- .TakeWhile(e => e.DeserializedEvent is not EntitySoftDeleted)
- .ToArray();
+ private async Task GrpcReadEventsFromStreamRaw(string id) {
+ var readResults = connV20.ReadStreamAsync(Direction.Forwards, id, StreamPosition.Start);
+ return await readResults
+ .Where(e => e.Event != null)
+ .Select(e => e.Event.ToStoredEvent(configuration.StateFactory))
+ .ToArrayAsync();
}
internal Task WriteEventsToStreamRaw(string currentStreamInUse, IEnumerable myEvents)
- => protocol switch
- {
- Protocol.Tcp => TcpWriteEventsToStreamRaw(currentStreamInUse, myEvents),
- Protocol.Grpc => GrpcWriteEventsToStreamRaw(currentStreamInUse, myEvents),
- _ => throw new ArgumentOutOfRangeException(nameof(protocol))
- };
-
- private async Task GrpcWriteEventsToStreamRaw(string currentStreamInUse, IEnumerable myEvents)
- {
- await connV20.AppendToStreamAsync(currentStreamInUse, ClientV20.StreamState.Any,
- myEvents.Select(e =>
- {
- var serialized = JsonConvert.SerializeObject(e);
- var bytes = System.Text.Encoding.UTF8.GetBytes(serialized);
- return new ClientV20.EventData(ClientV20.Uuid.NewUuid(), e.GetType().AssemblyQualifiedName, bytes, null);
- }));
+ => GrpcWriteEventsToStreamRaw(currentStreamInUse, myEvents);
+ private async Task GrpcWriteEventsToStreamRaw(string currentStreamInUse, IEnumerable myEvents) {
+ await connV20.AppendToStreamAsync(currentStreamInUse, StreamState.Any,
+ myEvents.Select(e => {
+ var serialized = JsonConvert.SerializeObject(e);
+ var bytes = System.Text.Encoding.UTF8.GetBytes(serialized);
+ return new EventData(Uuid.NewUuid(), e.GetType().AssemblyQualifiedName, bytes,
+ null);
+ }));
}
- private async Task TcpWriteEventsToStreamRaw(string currentStreamInUse, IEnumerable myEvents)
- {
- await connV5.AppendToStreamAsync(currentStreamInUse, ClientV5.ExpectedVersion.Any,
- myEvents.Select(e =>
- {
- var serialized = JsonConvert.SerializeObject(e);
- var bytes = System.Text.Encoding.UTF8.GetBytes(serialized);
- return new ClientV5.EventData(Guid.NewGuid(), e.GetType().AssemblyQualifiedName, true, bytes, null);
- }));
- }
- private async Task ConfigureEventStoreGrpc()
- {
+
+ private async Task ConfigureEventStoreGrpc() {
if (connV20 != null)
return connV20;
- var settings = ClientV20.EventStoreClientSettings
- .Create("esdb://localhost:2114?tls=false");
- var client = new ClientV20.EventStoreClient(settings);
- var projectionsClient = new ClientV20.EventStoreProjectionManagementClient(settings);
+ var settings = EventStoreClientSettings
+ .Create("esdb://localhost:2113?tls=false");
+ var client = new EventStoreClient(settings);
+ var projectionsClient = new EventStoreProjectionManagementClient(settings);
+
await projectionsClient.EnableAsync("$by_category");
await Task.Delay(TimeSpan.FromSeconds(3));
connV20 = client;
return client;
}
-
- private async Task ConfigureEventStoreTcp()
- {
- if (connV5 != null)
- return connV5;
-
- var connectionString =
- "ConnectTo=tcp://admin:changeit@localhost:1113;HeartBeatTimeout=500;UseSslConnection=false;";
- var builder = ClientV5.ConnectionSettings.Create()
- .KeepReconnecting();
-
- var connection = ClientV5.EventStoreConnection.Create(connectionString, builder);
-
- await connection.ConnectAsync();
-
- await Task.Delay(TimeSpan.FromSeconds(3));
- connV5 = connection;
- return connection;
- }
- public void Dispose()
- {
- connV5?.Dispose();
- }
}
}
diff --git a/src/BullOak.Repositories.EventStore.Test.Integration/Specification/ProtocolSpecs.feature b/src/BullOak.Repositories.EventStore.Test.Integration/Specification/ProtocolSpecs.feature
index 89cd7ef..3783ea6 100644
--- a/src/BullOak.Repositories.EventStore.Test.Integration/Specification/ProtocolSpecs.feature
+++ b/src/BullOak.Repositories.EventStore.Test.Integration/Specification/ProtocolSpecs.feature
@@ -12,5 +12,4 @@ Specs should be functional by both tcp and grpc protocols
And stream position should be 2
Examples:
| protocol |
- | tcp |
| grpc |
diff --git a/src/BullOak.Repositories.EventStore.Test.Integration/StepDefinitions/TestsSetupAndTeardown.cs b/src/BullOak.Repositories.EventStore.Test.Integration/StepDefinitions/TestsSetupAndTeardown.cs
index a091c32..dd3ff98 100644
--- a/src/BullOak.Repositories.EventStore.Test.Integration/StepDefinitions/TestsSetupAndTeardown.cs
+++ b/src/BullOak.Repositories.EventStore.Test.Integration/StepDefinitions/TestsSetupAndTeardown.cs
@@ -40,16 +40,10 @@ public static void TeardownNode()
EventStoreIntegrationContext.TeardownNode();
}
- [Given(@"the (tcp|grpc) protocol is being used")]
- public Task GivenProtocolIsBeingUsed(string protocol)
+ [Given(@"the grpc protocol is being used")]
+ public Task GivenProtocolIsBeingUsed()
{
- var chosenProtocol = Enum.Parse(ToCamelCase(protocol));
- return context.BuildRepositories(chosenProtocol);
- }
-
- private static string ToCamelCase(string text)
- {
- return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text);
+ return context.BuildRepositories();
}
}
}
diff --git a/src/BullOak.Repositories.EventStore.Test.Unit/BullOak.Repositories.EventStore.Test.Unit.csproj b/src/BullOak.Repositories.EventStore.Test.Unit/BullOak.Repositories.EventStore.Test.Unit.csproj
index dd921ab..002d6d9 100644
--- a/src/BullOak.Repositories.EventStore.Test.Unit/BullOak.Repositories.EventStore.Test.Unit.csproj
+++ b/src/BullOak.Repositories.EventStore.Test.Unit/BullOak.Repositories.EventStore.Test.Unit.csproj
@@ -1,23 +1,18 @@
- net6.0
- 9.0
+ net6.0;net7.0;net8.0;net9.0;net10.0
+ latest
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/BullOak.Repositories.EventStore.TestingExtras/BullOak.Repositories.EventStore.TestingExtras.csproj b/src/BullOak.Repositories.EventStore.TestingExtras/BullOak.Repositories.EventStore.TestingExtras.csproj
index 441a934..ebbada7 100644
--- a/src/BullOak.Repositories.EventStore.TestingExtras/BullOak.Repositories.EventStore.TestingExtras.csproj
+++ b/src/BullOak.Repositories.EventStore.TestingExtras/BullOak.Repositories.EventStore.TestingExtras.csproj
@@ -1,12 +1,9 @@
- netstandard2.1
+ net6.0;net7.0;net8.0;net9.0;net10.0
+ latest
enable
-
-
-
-
diff --git a/src/BullOak.Repositories.EventStore.sln b/src/BullOak.Repositories.EventStore.sln
deleted file mode 100644
index 501cf21..0000000
--- a/src/BullOak.Repositories.EventStore.sln
+++ /dev/null
@@ -1,74 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.2.32505.173
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BullOak.Repositories.EventStore", "BullOak.Repositories.EventStore\BullOak.Repositories.EventStore.csproj", "{4223C90A-73A2-4234-A240-10349B62C09C}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BullOak.Repositories.EventStore.Test.Integration", "BullOak.Repositories.EventStore.Test.Integration\BullOak.Repositories.EventStore.Test.Integration.csproj", "{FC55EB9E-4CBB-4A0E-BBDF-1E022B7679C1}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{ACD302AF-8190-4A7B-8888-48D7ECCC4829}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BullOak.Repositories.EventStore.Test.Unit", "BullOak.Repositories.EventStore.Test.Unit\BullOak.Repositories.EventStore.Test.Unit.csproj", "{E4A24EAC-FED4-4ECC-B5E0-C083E82C2792}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BullOak.Repositories.EventStore.ConsoleTestEventStoreClient", "BullOak.Repositories.EventStore.ConsoleTestEventStoreClient\BullOak.Repositories.EventStore.ConsoleTestEventStoreClient.csproj", "{896680DA-C076-403E-B117-3FEF57A919FE}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BullOak.Repositories.EventStore.TestingExtras", "BullOak.Repositories.EventStore.TestingExtras\BullOak.Repositories.EventStore.TestingExtras.csproj", "{C06585E1-718E-45D5-991D-E9B8ABD07FA9}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C396DBC5-B973-4E0A-83A9-509801AFE85E}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build scripts", "Build scripts", "{130AEC62-DF94-4C8B-90F3-89CEC4BBFD75}"
- ProjectSection(SolutionItems) = preProject
- ..\.github\workflows\build-on-push.yml = ..\.github\workflows\build-on-push.yml
- ..\.github\workflows\build-pr.yml = ..\.github\workflows\build-pr.yml
- ..\.github\workflows\build-version-tag.yml = ..\.github\workflows\build-version-tag.yml
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmark", "Benchmark\Benchmark.csproj", "{4A347281-E257-458A-91A4-9254EA8039EC}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {4223C90A-73A2-4234-A240-10349B62C09C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4223C90A-73A2-4234-A240-10349B62C09C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4223C90A-73A2-4234-A240-10349B62C09C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4223C90A-73A2-4234-A240-10349B62C09C}.Release|Any CPU.Build.0 = Release|Any CPU
- {FC55EB9E-4CBB-4A0E-BBDF-1E022B7679C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FC55EB9E-4CBB-4A0E-BBDF-1E022B7679C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FC55EB9E-4CBB-4A0E-BBDF-1E022B7679C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FC55EB9E-4CBB-4A0E-BBDF-1E022B7679C1}.Release|Any CPU.Build.0 = Release|Any CPU
- {E4A24EAC-FED4-4ECC-B5E0-C083E82C2792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E4A24EAC-FED4-4ECC-B5E0-C083E82C2792}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E4A24EAC-FED4-4ECC-B5E0-C083E82C2792}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E4A24EAC-FED4-4ECC-B5E0-C083E82C2792}.Release|Any CPU.Build.0 = Release|Any CPU
- {896680DA-C076-403E-B117-3FEF57A919FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {896680DA-C076-403E-B117-3FEF57A919FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {896680DA-C076-403E-B117-3FEF57A919FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {896680DA-C076-403E-B117-3FEF57A919FE}.Release|Any CPU.Build.0 = Release|Any CPU
- {C06585E1-718E-45D5-991D-E9B8ABD07FA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C06585E1-718E-45D5-991D-E9B8ABD07FA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C06585E1-718E-45D5-991D-E9B8ABD07FA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C06585E1-718E-45D5-991D-E9B8ABD07FA9}.Release|Any CPU.Build.0 = Release|Any CPU
- {4A347281-E257-458A-91A4-9254EA8039EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4A347281-E257-458A-91A4-9254EA8039EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4A347281-E257-458A-91A4-9254EA8039EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4A347281-E257-458A-91A4-9254EA8039EC}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {FC55EB9E-4CBB-4A0E-BBDF-1E022B7679C1} = {ACD302AF-8190-4A7B-8888-48D7ECCC4829}
- {E4A24EAC-FED4-4ECC-B5E0-C083E82C2792} = {ACD302AF-8190-4A7B-8888-48D7ECCC4829}
- {896680DA-C076-403E-B117-3FEF57A919FE} = {ACD302AF-8190-4A7B-8888-48D7ECCC4829}
- {C06585E1-718E-45D5-991D-E9B8ABD07FA9} = {ACD302AF-8190-4A7B-8888-48D7ECCC4829}
- {130AEC62-DF94-4C8B-90F3-89CEC4BBFD75} = {C396DBC5-B973-4E0A-83A9-509801AFE85E}
- {4A347281-E257-458A-91A4-9254EA8039EC} = {ACD302AF-8190-4A7B-8888-48D7ECCC4829}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {9FEF1659-166B-4856-B77C-3ABF38899EEB}
- EndGlobalSection
-EndGlobal
diff --git a/src/BullOak.Repositories.EventStore.slnx b/src/BullOak.Repositories.EventStore.slnx
new file mode 100644
index 0000000..437f288
--- /dev/null
+++ b/src/BullOak.Repositories.EventStore.slnx
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BullOak.Repositories.EventStore.v3.ncrunchsolution b/src/BullOak.Repositories.EventStore.v3.ncrunchsolution
new file mode 100644
index 0000000..5c70dc9
--- /dev/null
+++ b/src/BullOak.Repositories.EventStore.v3.ncrunchsolution
@@ -0,0 +1,8 @@
+
+
+ False
+ False
+ True
+ True
+
+
\ No newline at end of file
diff --git a/src/BullOak.Repositories.EventStore/BullOak.Repositories.EventStore.csproj b/src/BullOak.Repositories.EventStore/BullOak.Repositories.EventStore.csproj
index a2595e6..6cf215e 100644
--- a/src/BullOak.Repositories.EventStore/BullOak.Repositories.EventStore.csproj
+++ b/src/BullOak.Repositories.EventStore/BullOak.Repositories.EventStore.csproj
@@ -1,9 +1,9 @@
-
- net6.0
- True
+
+ net6.0;net7.0;net8.0;net9.0;net10.0
latest
+ True
true
@@ -28,12 +28,12 @@
-
+
1701;1702;NU5104;
-
+
1701;1702;NU5104;
@@ -42,13 +42,12 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/BullOak.Repositories.EventStore/EventStoreReadOnlyRepository.cs b/src/BullOak.Repositories.EventStore/EventStoreReadOnlyRepository.cs
index dcf6866..fff8f37 100644
--- a/src/BullOak.Repositories.EventStore/EventStoreReadOnlyRepository.cs
+++ b/src/BullOak.Repositories.EventStore/EventStoreReadOnlyRepository.cs
@@ -1,12 +1,8 @@
-using BullOak.Repositories.EventStore.Events;
-using BullOak.Repositories.EventStore.Metadata;
-using EventStore.Client;
-
-namespace BullOak.Repositories.EventStore
+namespace BullOak.Repositories.EventStore
{
+ using Events;
using System;
using System.Collections.Generic;
- using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Streams;
diff --git a/src/BullOak.Repositories.EventStore/Events/EventConversion.cs b/src/BullOak.Repositories.EventStore/Events/EventConversion.cs
index b1ac424..fdaf302 100644
--- a/src/BullOak.Repositories.EventStore/Events/EventConversion.cs
+++ b/src/BullOak.Repositories.EventStore/Events/EventConversion.cs
@@ -1,15 +1,17 @@
-namespace BullOak.Repositories.EventStore.Events
+
+
+namespace BullOak.Repositories.EventStore.Events
{
+
using Metadata;
using Newtonsoft.Json;
using StateEmit;
using System;
using System.Linq;
using System.Collections.Generic;
- using global::EventStore.Client;
- using global::EventStore.ClientAPI;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;
+ using global::EventStore.Client;
public static class EventConversion
{
@@ -26,19 +28,10 @@ public static StoredEvent ToStoredEvent(this EventRecord resolvedEvent, ICreateS
stateFactory
);
- public static StoredEvent ToStoredEvent(this RecordedEvent resolvedEvent, ICreateStateInstances stateFactory)
- => ToStoredEvent(
- resolvedEvent.EventStreamId,
- resolvedEvent.EventNumber,
- resolvedEvent.Data,
- resolvedEvent.Metadata,
- resolvedEvent.EventType,
- stateFactory
- );
-
public static StoredEvent ToStoredEvent(string streamId, long eventNumber, ReadOnlyMemory data, ReadOnlyMemory meta,
string eventTypeName, ICreateStateInstances stateFactory)
{
+
var serializedEvent = System.Text.Encoding.UTF8.GetString(data.Span);
var metadata = LoadMetadata(eventTypeName, meta);
diff --git a/src/BullOak.Repositories.EventStore/ItemWithTypeExtensions.cs b/src/BullOak.Repositories.EventStore/ItemWithTypeExtensions.cs
index 78b7cdf..ff007e8 100644
--- a/src/BullOak.Repositories.EventStore/ItemWithTypeExtensions.cs
+++ b/src/BullOak.Repositories.EventStore/ItemWithTypeExtensions.cs
@@ -1,13 +1,10 @@
namespace BullOak.Repositories.EventStore
{
- using System;
- using System.Globalization;
using Events;
using Metadata;
using Newtonsoft.Json.Linq;
using StateEmit;
using EsClientV20 = global::EventStore.Client;
- using EsClientV5 = global::EventStore.ClientAPI;
public static class ItemWithTypeExtensions
{
@@ -35,22 +32,6 @@ public static EsClientV20.EventData CreateV20EventData(this ItemWithType @event,
MetadataSerializer.Serialize(metadata));
}
- public static EsClientV5.EventData CreateV5EventData(this ItemWithType @event, IDateTimeProvider dateTimeProvider)
- {
- var metadata = EventMetadata_V2.From(@event);
- metadata.TimeStamp = dateTimeProvider.UtcNow;
-
- var eventAsJson = JObject.FromObject(@event.instance);
- eventAsJson.Remove(CanEditJsonFieldName);
-
- return new EsClientV5.EventData(
- Guid.NewGuid(),
- @event.type.Name,
- true,
- System.Text.Encoding.UTF8.GetBytes(eventAsJson.ToString()),
- MetadataSerializer.Serialize(metadata));
- }
-
public static bool IsSoftDeleteEvent(this ItemWithType @event)
=> @event.type == DefaultSoftDeleteEvent.Type || @event.type.IsSubclassOf(DefaultSoftDeleteEvent.Type);
}
diff --git a/src/BullOak.Repositories.EventStore/Protocol.cs b/src/BullOak.Repositories.EventStore/Protocol.cs
index 026cb00..13f769f 100644
--- a/src/BullOak.Repositories.EventStore/Protocol.cs
+++ b/src/BullOak.Repositories.EventStore/Protocol.cs
@@ -2,6 +2,5 @@ namespace BullOak.Repositories.EventStore;
public enum Protocol
{
- Tcp,
Grpc
}
diff --git a/src/BullOak.Repositories.EventStore/Streams/TcpEventReader.cs b/src/BullOak.Repositories.EventStore/Streams/TcpEventReader.cs
deleted file mode 100644
index 56a9a87..0000000
--- a/src/BullOak.Repositories.EventStore/Streams/TcpEventReader.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-namespace BullOak.Repositories.EventStore.Streams
-{
- using Events;
- using StateEmit;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using global::EventStore.ClientAPI;
- using System.Threading;
- using global::EventStore.ClientAPI.Exceptions;
-
- public class TcpEventReader : IReadEventsFromStream
- {
- private readonly ICreateStateInstances stateFactory;
- private readonly IEventStoreConnection connection;
- private readonly int pageSize;
- private static readonly IAsyncEnumerable EmptyReadResult = Array.Empty().ToAsyncEnumerable();
- private static readonly StoredEvent[] EmptyStoredEvents = new StoredEvent[0];
-
- public TcpEventReader(IEventStoreConnection client, IHoldAllConfiguration configuration, int pageSize = 4096)
- {
- stateFactory = configuration?.StateFactory ?? throw new ArgumentNullException(nameof(configuration));
- this.connection = client ?? throw new ArgumentNullException(nameof(client));
- this.pageSize = pageSize;
- }
-
- public async Task ReadToMemoryFrom(string streamId, Func predicate = null, StreamReadDirection direction = StreamReadDirection.Forwards, CancellationToken cancellationToken = default)
- {
- if (predicate == null)
- direction = StreamReadDirection.Forwards;
-
- predicate ??= _ => true;
-
- StoredEvent[] storedEvents;
- if (direction == StreamReadDirection.Backwards)
- {
- var readResult = await connection.ReadStreamEventsBackwardAsync(streamId, StreamPosition.End, pageSize, true);
-
- if (!StreamExists(readResult))
- return new StreamReadToMemoryResults(EmptyStoredEvents, false);
-
- storedEvents = readResult.Events
- // Trust me, resharper is wrong in this one. Event can be null
- // ReSharper disable once ConditionIsAlwaysTrueOrFalse
- .Where(e => e.Event != null)
- .Select((e, _) => e.Event.ToStoredEvent(stateFactory))
- .TakeWhile(e => e.DeserializedEvent is not EntitySoftDeleted)
- .Where(e => predicate(e))
- .ToArray();
- }
- else
- {
- var readResult = await connection.ReadStreamEventsForwardAsync(streamId, StreamPosition.Start, pageSize, true);
-
- if (!StreamExists(readResult))
- return new StreamReadToMemoryResults(EmptyStoredEvents, false);
-
- storedEvents = readResult.Events
- // Trust me, resharper is wrong in this one. Event can be null
- // ReSharper disable once ConditionIsAlwaysTrueOrFalse
- .Where(e => e.Event != null)
- .Select((e, c) => e.Event.ToStoredEvent(stateFactory))
- .Where(e => predicate(e))
- .ToArray();
- }
-
- return new StreamReadToMemoryResults(storedEvents, true);
- }
-
- public async Task ReadFrom(string streamId, Func predicate = null, StreamReadDirection direction = StreamReadDirection.Forwards, CancellationToken cancellationToken = default)
- {
- var readToMemResults = await ReadToMemoryFrom(streamId, predicate, direction, cancellationToken);
- return new StreamReadResults(readToMemResults.Events.ToAsyncEnumerable(), readToMemResults.StreamExists);
- }
-
- private static bool StreamExists(StreamEventsSlice readResult)
- {
- bool streamExists = false;
- try
- {
- var readState = readResult.Status;
- streamExists = readState == SliceReadStatus.Success;
- }
-#pragma warning disable 168
- catch (StreamDeletedException ex)
- // This happens when the stream is hard-deleted. We don't want to throw in that case
-#pragma warning restore 168
- {
- streamExists = false;
- }
-
- return streamExists;
- }
- }
-}
diff --git a/src/BullOak.Repositories.EventStore/Streams/TcpEventWriter.cs b/src/BullOak.Repositories.EventStore/Streams/TcpEventWriter.cs
deleted file mode 100644
index aff16e7..0000000
--- a/src/BullOak.Repositories.EventStore/Streams/TcpEventWriter.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-namespace BullOak.Repositories.EventStore.Streams;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Exceptions;
-using global::EventStore.ClientAPI;
-
-public class TcpEventWriter : IStoreEventsToStream
-{
- private readonly IEventStoreConnection connection;
-
- public TcpEventWriter(IEventStoreConnection connection)
- {
- this.connection = connection;
- }
-
- public async Task Add
- (
- string streamId,
- ItemWithType[] eventsToAdd,
- IDateTimeProvider dateTimeProvider,
- CancellationToken cancellationToken = default
- ) => await AppendToStream(streamId, -1, eventsToAdd, dateTimeProvider, cancellationToken);
-
-
- public async Task AppendTo
- (
- string streamId,
- long revision,
- ItemWithType[] eventsToAdd,
- IDateTimeProvider dateTimeProvider,
- CancellationToken cancellationToken = default
- ) => await AppendToStream(streamId, revision, eventsToAdd, dateTimeProvider, cancellationToken);
-
- public async Task SoftDelete(string streamId)
- {
- var expectedVersion = await GetLastEventNumber(streamId);
- await connection.DeleteStreamAsync(streamId, expectedVersion);
- }
-
- public async Task SoftDeleteByEvent(string streamId, IEnumerable eventData)
- {
- var events = eventData as EventData[] ?? eventData.Cast().ToArray();
-
- var expectedVersion = await GetLastEventNumber(streamId);
- var writeResult = await connection.ConditionalAppendToStreamAsync
- (
- streamId,
- expectedVersion,
- events
- )
- .ConfigureAwait(false);
-
- CheckConditionalWriteResultStatus(writeResult, streamId);
- }
-
- private async Task GetLastEventNumber(string id)
- {
- var eventsTail = await GetLastEvent(id);
- return eventsTail.LastEventNumber;
- }
-
- private Task GetLastEvent(string id)
- => connection.ReadStreamEventsBackwardAsync(id, StreamPosition.End, 1, false);
-
- private async Task AppendToStream
- (
- string streamId,
- long revision,
- ItemWithType[] eventsToAdd,
- IDateTimeProvider dateTimeProvider,
- CancellationToken cancellationToken
- )
- {
- var writeResult = await connection.ConditionalAppendToStreamAsync(
- streamId,
- revision,
- eventsToAdd.Select(eventObject => eventObject.CreateV5EventData(dateTimeProvider))
- )
- .ConfigureAwait(false);
-
- CheckConditionalWriteResultStatus(writeResult, streamId);
-
- if (!writeResult.NextExpectedVersion.HasValue)
- {
- throw new InvalidOperationException(
- "EventStore data write outcome unexpected. NextExpectedVersion is null");
- }
-
- return (int)writeResult.NextExpectedVersion;
- }
-
-
- private static void CheckConditionalWriteResultStatus(ConditionalWriteResult writeResult, string id)
- {
- switch (writeResult.Status)
- {
- case ConditionalWriteStatus.Succeeded:
- break;
- case ConditionalWriteStatus.VersionMismatch:
- throw new ConcurrencyException(id, null);
- case ConditionalWriteStatus.StreamDeleted:
- throw new InvalidOperationException($"Stream was deleted. StreamId: {id}");
- default:
- throw new InvalidOperationException($"Unexpected write result: {writeResult.Status}");
- }
- }
-}
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
new file mode 100644
index 0000000..4c07f19
--- /dev/null
+++ b/src/Directory.Packages.props
@@ -0,0 +1,29 @@
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/dotnet-tools.json b/src/dotnet-tools.json
new file mode 100644
index 0000000..316872e
--- /dev/null
+++ b/src/dotnet-tools.json
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "dotnet-purge": {
+ "version": "0.0.13",
+ "commands": [
+ "dotnet-purge"
+ ],
+ "rollForward": false
+ }
+ }
+}
\ No newline at end of file