Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
<MicrosoftExtensionsVer>9.0.10</MicrosoftExtensionsVer>
</PropertyGroup>
<PropertyGroup Label="Testcontainers version">
<TestcontainersVersion>4.8.1</TestcontainersVersion>
<TestcontainersVersion>4.10.0</TestcontainersVersion>
</PropertyGroup>
<PropertyGroup>
<NpgsqlVersion>9.0.3</NpgsqlVersion>
<NpgsqlVersion>10.0.1</NpgsqlVersion>
<TUnitVersion>0.77.3</TUnitVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="FluentValidation" Version="12.0.0" />
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
<PackageVersion Include="KurrentDB.Client" Version="1.3.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftExtensionsVer)" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsVer)" />
Expand Down Expand Up @@ -59,7 +60,7 @@
</ItemGroup>
<ItemGroup Label="Testcontainers">
<PackageVersion Include="Testcontainers" Version="$(TestcontainersVersion)" />
<PackageVersion Include="Testcontainers.EventStoreDb" Version="$(TestcontainersVersion)" />
<PackageVersion Include="Testcontainers.KurrentDb" Version="$(TestcontainersVersion)" />
<PackageVersion Include="Testcontainers.Kafka" Version="$(TestcontainersVersion)" />
<PackageVersion Include="Testcontainers.MongoDb" Version="$(TestcontainersVersion)" />
<PackageVersion Include="Testcontainers.PostgreSql" Version="$(TestcontainersVersion)" />
Expand All @@ -82,7 +83,7 @@
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="$(MicrosoftTestHostVer)" />
<PackageVersion Include="RestSharp" Version="112.1.0" />
<PackageVersion Include="Hypothesist" Version="3.0.97" />
<PackageVersion Include="NodaTime" Version="3.2.2" />
<PackageVersion Include="NodaTime" Version="3.3.0" />
<PackageVersion Include="NodaTime.Serialization.SystemTextJson" Version="1.2.0" />
<PackageVersion Include="MongoDb.Bson.NodaTime" Version="3.1.0" />
<PackageVersion Include="Verify.DiffPlex" Version="3.1.2" />
Expand Down
5 changes: 5 additions & 0 deletions Eventuous.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
<Project Path="src/Diagnostics/test/Eventuous.Tests.OpenTelemetry/Eventuous.Tests.OpenTelemetry.csproj" />
</Folder>
<Folder Name="/Experimental/" />
<Folder Name="/Experimental/gen/">
<Project Path="src/Experimental/gen/Eventuous.Spyglass.Generators/Eventuous.Spyglass.Generators.csproj" />
</Folder>
<Folder Name="/Experimental/src/">
<Project Path="src/Experimental/src/ElasticPlayground/ElasticPlayground.csproj" />
<Project Path="src/Experimental/src/Eventuous.ElasticSearch/Eventuous.ElasticSearch.csproj" />
Expand All @@ -81,6 +84,8 @@
</Folder>
<Folder Name="/Experimental/test/">
<Project Path="src/Redis/test/Eventuous.Tests.Redis/Eventuous.Tests.Redis.csproj" />
<Project Path="src/Experimental/test/Eventuous.Tests.Spyglass.Generators/Eventuous.Tests.Spyglass.Generators.csproj" />
<Project Path="src/Experimental/test/Eventuous.Tests.Spyglass/Eventuous.Tests.Spyglass.csproj" />
</Folder>
<Folder Name="/Extensions/" />
<Folder Name="/Extensions/gen/">
Expand Down
2 changes: 1 addition & 1 deletion samples/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>preview</LangVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

namespace Bookings.Payments.Application;

public class CommandService : CommandService<Payment, PaymentState, PaymentId> {
public class CommandService : CommandService<PaymentState> {
public CommandService(IEventStore store) : base(store) {
On<PaymentCommands.RecordPayment>()
.InState(ExpectedState.New)
.GetId(cmd => new(cmd.PaymentId))
.Act((payment, cmd) => payment.ProcessPayment(cmd.BookingId, new(cmd.Amount, cmd.Currency), cmd.Method, cmd.Provider));
.GetStream(cmd => GetStream(cmd.PaymentId))
.Act(cmd => [new PaymentEvents.PaymentRecorded(cmd.BookingId, cmd.Amount, cmd.Currency, cmd.Method, cmd.Provider)]);
}
}

Expand Down
4 changes: 4 additions & 0 deletions samples/kurrentdb/Bookings.Payments/Bookings.Payments.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<Configurations>Debug;Release</Configurations>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>obj/Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver.Core.Extensions.DiagnosticSources"/>
Expand Down Expand Up @@ -30,5 +32,7 @@
<ProjectReference Include="$(SrcRoot)\Gateway\src\Eventuous.Gateway\Eventuous.Gateway.csproj"/>
<ProjectReference Include="$(SrcRoot)\Core\gen\Eventuous.Subscriptions.Generators\Eventuous.Subscriptions.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="$(SrcRoot)\Core\gen\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="$(SrcRoot)\Experimental\src\Eventuous.Spyglass\Eventuous.Spyglass.csproj"/>
<ProjectReference Include="$(SrcRoot)\Experimental\gen\Eventuous.Spyglass.Generators\Eventuous.Spyglass.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
10 changes: 2 additions & 8 deletions samples/kurrentdb/Bookings.Payments/Domain/Payment.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
using Eventuous;
using static Bookings.Payments.Domain.PaymentEvents;

namespace Bookings.Payments.Domain;

public class Payment : Aggregate<PaymentState> {
public void ProcessPayment(string bookingId, Money amount, string method, string provider)
=> Apply(new PaymentRecorded(bookingId, amount.Amount, amount.Currency, method, provider));
}
using static PaymentEvents;

public record PaymentState : State<PaymentState> {
public string BookingId { get; init; } = null!;
Expand All @@ -15,6 +11,4 @@ public record PaymentState : State<PaymentState> {
public PaymentState() {
On<PaymentRecorded>((state, recorded) => state with { BookingId = recorded.BookingId, Amount = recorded.Amount });
}
}

public record PaymentId(string Value) : Id(Value);
}
3 changes: 3 additions & 0 deletions samples/kurrentdb/Bookings.Payments/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Bookings.Payments;
using Bookings.Payments.Domain;
using Bookings.Payments.Infrastructure;
using Eventuous.Spyglass;
using Serilog;

Logging.ConfigureLog();
Expand All @@ -27,4 +28,6 @@

app.UseSwaggerUI();

app.MapEventuousSpyglass();

app.Run();
1 change: 1 addition & 0 deletions samples/kurrentdb/Bookings/Bookings.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<ProjectReference Include="$(SrcRoot)\Extensions\src\Eventuous.Extensions.AspNetCore\Eventuous.Extensions.AspNetCore.csproj"/>
<ProjectReference Include="$(SrcRoot)\Core\gen\Eventuous.Subscriptions.Generators\Eventuous.Subscriptions.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="$(SrcRoot)\Core\gen\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="$(SrcRoot)\Experimental\gen\Eventuous.Spyglass.Generators\Eventuous.Spyglass.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\Bookings.Domain\Bookings.Domain.csproj"/>
</ItemGroup>
<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion samples/kurrentdb/Bookings/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
builder.Services.AddSwaggerGen();
builder.Services.AddTelemetry();
builder.Services.AddEventuous(builder.Configuration);
builder.Services.AddEventuousSpyglass();
builder.Services.Configure<JsonOptions>(options => options.SerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb));

var app = builder.Build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Testcontainers.ServiceBus" />
<PackageReference Update="coverlet.collector">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ public SendAndReceive(AzureServiceBusFixture fixture, ServiceBusProducerOptions
_metadata = new Metadata().With(MetaTags.CorrelationId, _correlationId);
_serviceBusProducerOptions = producerOptions;
_serviceBusSubscriptionOptions = subscriptionOptions;
this._fixture = fixture;
_fixture = fixture;
}

[Test]
[Retry(3)]
public async Task SingleMessage() {
await _producer.Produce(_streamName, SomeEvent.Create(), _metadata, cancellationToken: TestCancellationToken);

Expand All @@ -42,6 +43,7 @@ await _handler.AssertThat()
}

[Test]
[Retry(3)]
public async Task LoadsOfMessages() {
const int count = 200;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public IDisposable OldLoggingScope() {
{ "Stream", "TestStream" },
{ "MessageType", "TestMessage" }
};
return TestLogger.BeginScope(scope);
return TestLogger.BeginScope(scope)!;
}

[Benchmark(Description = "NEW: Logging scope with KeyValuePair array")]
Expand All @@ -107,7 +107,7 @@ public IDisposable NewLoggingScope() {
new("Stream", "TestStream"),
new("MessageType", "TestMessage")
};
return TestLogger.BeginScope(scope);
return TestLogger.BeginScope(scope)!;
}

// ===== Issue #6: CancellationTokenSource Guards =====
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,4 @@
<AdditionalFiles Remove="AnalyzerReleases.Shipped.md" />
<AdditionalFiles Remove="AnalyzerReleases.Unshipped.md" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Polyfills\**" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove="Polyfills\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Polyfills\**" />
</ItemGroup>
</Project>
12 changes: 7 additions & 5 deletions src/Core/src/Eventuous.Domain/State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@

namespace Eventuous;

[Obsolete("Use State<T> instead")]
public abstract record AggregateState<T> : State<T> where T : AggregateState<T>;

[PublicAPI]
public abstract record State<T> where T : State<T> {
/// <summary>
/// Function to apply event to the state object.
/// Function to apply an event to the state object.
/// </summary>
/// <param name="event">Event to apply</param>
/// <returns>New instance of state</returns>
Expand All @@ -24,7 +21,7 @@ public virtual T When(object @event) {
/// <summary>
/// Event handler that uses the event payload and creates a new instance of state using the data from the event.
/// </summary>
/// <param name="handle">Function to return new state instance after the event is applied</param>
/// <param name="handle">Function to return a new state instance after the event is applied</param>
/// <typeparam name="TEvent">Event type</typeparam>
/// <exception cref="Exceptions.DuplicateTypeException{T}">Thrown if another function already handles this event type</exception>
[PublicAPI]
Expand All @@ -36,6 +33,11 @@ protected void On<TEvent>(Func<T, TEvent, T> handle) {
}
}

/// <summary>
/// Returns the event types that have registered handlers in this state.
/// </summary>
public ICollection<Type> GetRegisteredEventTypes() => _handlers.Keys;

readonly Dictionary<Type, Func<T, object, T>> _handlers = new();
}

Expand Down
25 changes: 25 additions & 0 deletions src/Core/src/Eventuous.Persistence/StreamNameMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,40 @@

namespace Eventuous;

/// <summary>
/// Provides a mapping mechanism for generating stream names from aggregate identifiers.
/// Allows custom stream name generation strategies to be registered for different identifier types.
/// </summary>
public class StreamNameMap {
readonly TypeMap<Func<Id, StreamName>> _typeMap = new();

/// <summary>
/// Registers a custom stream name mapping function for a specific identifier type.
/// </summary>
/// <typeparam name="TId">The type of the identifier that inherits from <see cref="Id"/>.</typeparam>
/// <param name="map">A function that maps an identifier of type <typeparamref name="TId"/> to a <see cref="StreamName"/>.</param>
public void Register<TId>(Func<TId, StreamName> map) where TId : Id => _typeMap.Add<TId>(id => map((TId)id));

/// <summary>
/// Gets the stream name for an aggregate with a specific identifier.
/// Uses the registered mapping function if available, otherwise falls back to the default factory.
/// </summary>
/// <typeparam name="T">The type of the aggregate that inherits from <see cref="Aggregate{TState}"/>.</typeparam>
/// <typeparam name="TState">The type of the aggregate state that inherits from <see cref="State{TState}"/>.</typeparam>
/// <typeparam name="TId">The type of the aggregate identifier that inherits from <see cref="Id"/>.</typeparam>
/// <param name="aggregateId">The aggregate identifier to map to a stream name.</param>
/// <returns>A <see cref="StreamName"/> for the specified aggregate identifier.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public StreamName GetStreamName<T, TState, TId>(TId aggregateId) where TId : Id where T : Aggregate<TState> where TState : State<TState>, new()
=> _typeMap.TryGetValue<TId>(out var map) ? map(aggregateId) : StreamNameFactory.For<T, TState, TId>(aggregateId);

/// <summary>
/// Gets the stream name for a specific identifier.
/// Uses the registered mapping function if available, otherwise falls back to the default factory.
/// </summary>
/// <typeparam name="TId">The type of the identifier that inherits from <see cref="Id"/>.</typeparam>
/// <param name="id">The identifier to map to a stream name.</param>
/// <returns>A <see cref="StreamName"/> for the specified identifier.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public StreamName GetStreamName<TId>(TId id) where TId : Id => _typeMap.TryGetValue<TId>(out var map) ? map(id) : StreamNameFactory.For(id);
}
2 changes: 1 addition & 1 deletion src/Core/src/Eventuous.Shared/Eventuous.Shared.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<PackageReference Include="System.Diagnostics.DiagnosticSource"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\gen\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" ReferenceOutputAssembly="false" PackAsAnalyzer="true"/>
<ProjectReference Include="$(LocalGenRoot)\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" ReferenceOutputAssembly="false" PackAsAnalyzer="true"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Exceptions\ExceptionMessages.restext">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<ProjectReference Include="..\Eventuous.Serialization\Eventuous.Serialization.csproj"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\gen\Eventuous.Subscriptions.Generators\Eventuous.Subscriptions.Generators.csproj" ReferenceOutputAssembly="false" PackAsAnalyzer="true"/>
<ProjectReference Include="$(LocalGenRoot)\Eventuous.Subscriptions.Generators\Eventuous.Subscriptions.Generators.csproj" ReferenceOutputAssembly="false" PackAsAnalyzer="true"/>
</ItemGroup>
<ItemGroup>
<None Remove="Eventuous.Subscriptions.csproj.DotSettings"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@
<DependentUpon>ServiceTestBase.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Update="coverlet.collector">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
<PackageReference Include="NodaTime.Bogus" />
<PackageReference Include="Microsoft.CodeAnalysis" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Update="coverlet.collector">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(LocalRoot)\Eventuous.Application\Eventuous.Application.csproj"/>
<ProjectReference Include="$(SrcRoot)\Testing\src\Eventuous.Testing\Eventuous.Testing.csproj"/>
<ProjectReference Include="..\..\gen\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" />
<ProjectReference Include="$(LocalGenRoot)\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging.Abstractions;
using Shouldly;
#pragma warning disable CS9113 // Parameter is unread.

namespace Eventuous.Tests.Subscriptions;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Shouldly" />
<PackageReference Update="coverlet.collector">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
6 changes: 5 additions & 1 deletion src/Core/test/Eventuous.Tests/Eventuous.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
<PackageReference Include="NodaTime.Bogus" />
<PackageReference Include="Microsoft.CodeAnalysis" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Update="coverlet.collector">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(LocalRoot)\Eventuous.Application\Eventuous.Application.csproj"/>
<ProjectReference Include="$(SrcRoot)\Testing\src\Eventuous.Testing\Eventuous.Testing.csproj"/>
<ProjectReference Include="..\..\gen\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="$(LocalGenRoot)\Eventuous.Shared.Generators\Eventuous.Shared.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<ExtRoot>$(SrcRoot)\Extensions\src</ExtRoot>
<GatewayRoot>$(SrcRoot)\Shovel\src</GatewayRoot>
<LocalRoot>..\..\src</LocalRoot>
<LocalGenRoot>..\..\gen</LocalGenRoot>
<Configurations>Debug;Release;Debug CI</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
Expand Down
8 changes: 0 additions & 8 deletions src/Directory.Build.targets

This file was deleted.

8 changes: 0 additions & 8 deletions src/Directory.Testable.targets

This file was deleted.

Loading
Loading