From d804a007af97c9c4ac6747d42ba9c4fa3c880a1a Mon Sep 17 00:00:00 2001 From: Oskar Dudycz Date: Sat, 26 Nov 2022 13:20:46 +0100 Subject: [PATCH] Got rid of MediatR in QueryBus --- CQRS.Tests/CQRS.Tests.csproj | 28 ---- CQRS.Tests/Commands/Commands.cs | 120 ----------------- CQRS.Tests/Queries/Queries.cs | 121 ------------------ .../TestsInfrasructure/ServiceLocator.cs | 38 ------ Core/Commands/Config.cs | 3 +- Core/Commands/Mediator/ICommand.cs | 5 - Core/Commands/Mediator/IMediatorCommandBus.cs | 6 - .../Mediator/IMediatorCommandHandler.cs | 8 -- Core/Commands/Mediator/MediatorCommandBus.cs | 18 --- Core/Config.cs | 14 +- Core/Core.csproj | 1 - Core/Events/Mediator/IEvent.cs | 7 - Core/Events/Mediator/IMediatorEventHandler.cs | 23 ---- Core/Events/Mediator/MediatorEventBus.cs | 34 ----- Core/OpenTelemetry/TelemetryTags.cs | 5 + Core/Queries/Config.cs | 8 +- Core/Queries/IQuery.cs | 7 - Core/Queries/IQueryBus.cs | 5 +- Core/Queries/IQueryHandler.cs | 9 +- Core/Queries/QueryBus.cs | 57 ++++++++- .../EventSourcing.Integration.Tests.csproj | 1 - EventSourcing.NetCore.sln | 14 -- .../Initialization/Initialization.cs | 36 ------ MediatR.Tests/MediatR.Tests.csproj | 31 ----- .../Publishing/MoreThanOneHandler.cs | 84 ------------ MediatR.Tests/Publishing/NoHandlers.cs | 59 --------- MediatR.Tests/Publishing/SingleHandler.cs | 85 ------------ MediatR.Tests/Sending/MoreThanOneHandler.cs | 85 ------------ MediatR.Tests/Sending/NoHandlers.cs | 59 --------- MediatR.Tests/Sending/SingleHandler.cs | 86 ------------- MediatR.Tests/xunit.runner.json | 3 - README.md | 112 +++++++--------- .../Controllers/MotionSensorsController.cs | 2 +- .../TemperatureMeasurementsController.cs | 2 +- .../GettingMotionSensor/GetMotionSensor.cs | 9 +- .../GetTemperatureMeasurements.cs | 2 +- .../Controllers/ShoppingCartsController.cs | 8 +- .../GettingCartAtVersion/GetCartAtVersion.cs | 2 +- .../GettingCartById/GetCartById.cs | 2 +- .../GettingCartHistory/GetCartHistory.cs | 2 +- .../ShoppingCarts/GettingCarts/GetCarts.cs | 2 +- .../Controllers/ShoppingCartsController.cs | 8 +- .../GettingCartAtVersion/GetCartAtVersion.cs | 2 +- .../GettingCartById/GetCartById.cs | 2 +- .../GettingCartHistory/GetCartHistory.cs | 2 +- .../ShoppingCarts/GettingCarts/GetCarts.cs | 2 +- .../Controllers/MeetingsController.cs | 2 +- .../Meetings/GettingMeeting/GetMeeting.cs | 4 +- .../Controllers/MeetingsController.cs | 2 +- .../SearchingMeetings/SearchMeetings.cs | 4 +- .../Controllers/ReservationsController.cs | 8 +- .../CreateTentativeReservation.cs | 2 +- .../GetReservationAtVersion.cs | 2 +- .../GetReservationById.cs | 4 +- .../GetReservationHistory.cs | 2 +- .../GettingReservations/GetReservations.cs | 2 +- 56 files changed, 154 insertions(+), 1097 deletions(-) delete mode 100644 CQRS.Tests/CQRS.Tests.csproj delete mode 100644 CQRS.Tests/Commands/Commands.cs delete mode 100644 CQRS.Tests/Queries/Queries.cs delete mode 100644 CQRS.Tests/TestsInfrasructure/ServiceLocator.cs delete mode 100644 Core/Commands/Mediator/ICommand.cs delete mode 100644 Core/Commands/Mediator/IMediatorCommandBus.cs delete mode 100644 Core/Commands/Mediator/IMediatorCommandHandler.cs delete mode 100644 Core/Commands/Mediator/MediatorCommandBus.cs delete mode 100644 Core/Events/Mediator/IEvent.cs delete mode 100644 Core/Events/Mediator/IMediatorEventHandler.cs delete mode 100644 Core/Events/Mediator/MediatorEventBus.cs delete mode 100644 Core/Queries/IQuery.cs delete mode 100644 MediatR.Tests/Initialization/Initialization.cs delete mode 100644 MediatR.Tests/MediatR.Tests.csproj delete mode 100644 MediatR.Tests/Publishing/MoreThanOneHandler.cs delete mode 100644 MediatR.Tests/Publishing/NoHandlers.cs delete mode 100644 MediatR.Tests/Publishing/SingleHandler.cs delete mode 100644 MediatR.Tests/Sending/MoreThanOneHandler.cs delete mode 100644 MediatR.Tests/Sending/NoHandlers.cs delete mode 100644 MediatR.Tests/Sending/SingleHandler.cs delete mode 100644 MediatR.Tests/xunit.runner.json diff --git a/CQRS.Tests/CQRS.Tests.csproj b/CQRS.Tests/CQRS.Tests.csproj deleted file mode 100644 index 8b422c66a..000000000 --- a/CQRS.Tests/CQRS.Tests.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net7.0 - - - - - PreserveNewest - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - diff --git a/CQRS.Tests/Commands/Commands.cs b/CQRS.Tests/Commands/Commands.cs deleted file mode 100644 index 1c1103aba..000000000 --- a/CQRS.Tests/Commands/Commands.cs +++ /dev/null @@ -1,120 +0,0 @@ -using CQRS.Tests.TestsInfrasructure; -using FluentAssertions; -using MediatR; -using Xunit; - -namespace CQRS.Tests.Commands; - -public class Commands -{ - public interface ICommand: IRequest - { } - - public interface ICommandHandler: IRequestHandler where T : ICommand - { } - - public interface ICommandBus - { - Task Send(ICommand command); - } - - public class CommandBus: ICommandBus - { - private readonly IMediator mediator; - - public CommandBus(IMediator mediator) - { - this.mediator = mediator; - } - - public Task Send(ICommand command) - { - return mediator.Send(command); - } - } - - public class CreateIssueCommand: ICommand - { - public string Name { get; } - - public CreateIssueCommand(string name) - { - Name = name; - } - } - - public interface IIssueApplicationService - { - Task CreateIssue(CreateIssueCommand command); - } - - public class IssueApplicationService: IIssueApplicationService - { - private readonly ICommandBus commandBus; - - public IssueApplicationService(ICommandBus commandBus) - { - this.commandBus = commandBus; - } - - public Task CreateIssue(CreateIssueCommand command) - { - return commandBus.Send(command); - } - } - - public interface IAppWrtiteModel - { - IList Issues { get; } - } - - public class AppWriteModel: IAppWrtiteModel - { - public IList Issues { get; } - - public AppWriteModel(params string[] issues) - { - Issues = new List(); - } - } - - public class CreateIssueCommandHandler: ICommandHandler - { - private readonly IAppWrtiteModel writeModel; - - public CreateIssueCommandHandler(IAppWrtiteModel writeModel) - { - this.writeModel = writeModel; - } - - public Task Handle(CreateIssueCommand message, CancellationToken cancellationToken = default) - { - writeModel.Issues.Add(message.Name); - return Unit.Task; - } - } - - [Fact] - public void GivenCommandWithData_WhenCommandIsSendToApplicationService_ThenWriteModelIsChanged() - { - var serviceLocator = new ServiceLocator(); - - var writeModel = new AppWriteModel(); - var commandHandler = new CreateIssueCommandHandler(writeModel); - serviceLocator.RegisterCommandHandler(commandHandler); - - var applicationService = new IssueApplicationService(new CommandBus(serviceLocator.GetMediator())); - - //Given - var createdIssueName = "cleaning"; - - var command = new CreateIssueCommand(createdIssueName); - - //When - applicationService.CreateIssue(command); - - //Then - writeModel.Issues.Should().HaveCount(1); - writeModel.Issues.Should().BeEquivalentTo(createdIssueName); - } -} diff --git a/CQRS.Tests/Queries/Queries.cs b/CQRS.Tests/Queries/Queries.cs deleted file mode 100644 index bde63f35a..000000000 --- a/CQRS.Tests/Queries/Queries.cs +++ /dev/null @@ -1,121 +0,0 @@ -using CQRS.Tests.TestsInfrasructure; -using FluentAssertions; -using MediatR; -using Xunit; - -namespace CQRS.Tests.Queries; - -public class Queries -{ - public interface IQuery: IRequest - { } - - public interface IQueryHandler: IRequestHandler - where TQuery : IQuery - { } - - public interface IQueryBus - { - Task Send(IQuery command); - } - - public class QueryBus: IQueryBus - { - private readonly IMediator mediator; - - public QueryBus(IMediator mediator) - { - this.mediator = mediator; - } - - public Task Send(IQuery command) - { - return mediator.Send(command); - } - } - - public class GetIssuesNamesQuery: IQuery> - { - public string Filter { get; } - - public GetIssuesNamesQuery(string filter) - { - Filter = filter; - } - } - - public interface IIssueApplicationService - { - Task> GetIssuesNames(GetIssuesNamesQuery query); - } - - public class IssueApplicationService: IIssueApplicationService - { - private readonly IQueryBus queryBus; - - public IssueApplicationService(IQueryBus queryBus) - { - this.queryBus = queryBus; - } - - public Task> GetIssuesNames(GetIssuesNamesQuery query) - { - return queryBus.Send(query); - } - } - - public interface IAppReadModel - { - IQueryable Issues { get; } - } - - public class AppReadModel: IAppReadModel - { - private readonly IList issues; - public IQueryable Issues => issues.AsQueryable(); - - public AppReadModel(params string[] issues) - { - this.issues = issues.ToList(); - } - } - - public class CreateIssueCommandHandler: IQueryHandler> - { - private readonly IAppReadModel readModel; - - public CreateIssueCommandHandler(IAppReadModel readModel) - { - this.readModel = readModel; - } - - public Task> Handle(GetIssuesNamesQuery query, CancellationToken cancellationToken = default(CancellationToken)) - { - return Task.Run(() => readModel.Issues - .Where(taskName => taskName.ToLower().Contains(query.Filter.ToLower())) - .ToList(), cancellationToken); - } - } - - [Fact] - public async Task GivenCommandWithData_WhenCommandIsSendToApplicationService_ThenreadModelIsChanged() - { - var serviceLocator = new ServiceLocator(); - - var readModel = new AppReadModel("Cleaning main room", "Writing blog", "cleaning kitchen"); - var commandHandler = new CreateIssueCommandHandler(readModel); - serviceLocator.RegisterQueryHandler(commandHandler); - - var applicationService = new IssueApplicationService(new QueryBus(serviceLocator.GetMediator())); - - //Given - var query = new GetIssuesNamesQuery("cleaning"); - - //When - var result = await applicationService.GetIssuesNames(query); - - //Then - result.Should().HaveCount(2); - result.Should().BeEquivalentTo("Cleaning main room", "cleaning kitchen"); - } -} diff --git a/CQRS.Tests/TestsInfrasructure/ServiceLocator.cs b/CQRS.Tests/TestsInfrasructure/ServiceLocator.cs deleted file mode 100644 index 77b3a9309..000000000 --- a/CQRS.Tests/TestsInfrasructure/ServiceLocator.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MediatR; - -namespace CQRS.Tests.TestsInfrasructure; - -public class ServiceLocator -{ - private readonly Dictionary> services = new(); - - public void Register(Type type, params object[] implementations) - => services.Add(type, implementations.ToList()); - - public List Get(Type type) - { - return services[type]; - } - - public void RegisterCommandHandler(TCommandHandler commandHandler) - where TCommand : IRequest - where TCommandHandler : IRequestHandler - { - Register(typeof(IRequestHandler), commandHandler); - //Registration needed internally by MediatR - Register(typeof(IEnumerable>), new List>()); - } - - public void RegisterQueryHandler(IRequestHandler queryHandler) - where TQuery : IRequest - { - Register(typeof(IRequestHandler), queryHandler); - //Registration needed internally by MediatR - Register(typeof(IEnumerable>), new List>()); - } - - public IMediator GetMediator() - { - return new Mediator(type => Get(type).First()); - } -} diff --git a/Core/Commands/Config.cs b/Core/Commands/Config.cs index acfaf5781..ab3a9ee5b 100644 --- a/Core/Commands/Config.cs +++ b/Core/Commands/Config.cs @@ -1,5 +1,4 @@ -using MediatR; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace Core.Commands; diff --git a/Core/Commands/Mediator/ICommand.cs b/Core/Commands/Mediator/ICommand.cs deleted file mode 100644 index e858b57f4..000000000 --- a/Core/Commands/Mediator/ICommand.cs +++ /dev/null @@ -1,5 +0,0 @@ -using MediatR; - -namespace Core.Commands; - -public interface ICommand: IRequest { } \ No newline at end of file diff --git a/Core/Commands/Mediator/IMediatorCommandBus.cs b/Core/Commands/Mediator/IMediatorCommandBus.cs deleted file mode 100644 index bbe24fa7e..000000000 --- a/Core/Commands/Mediator/IMediatorCommandBus.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Core.Commands.Mediator; - -public interface IMediatorCommandBus -{ - Task Send(TCommand command) where TCommand : ICommand; -} diff --git a/Core/Commands/Mediator/IMediatorCommandHandler.cs b/Core/Commands/Mediator/IMediatorCommandHandler.cs deleted file mode 100644 index 92177ea82..000000000 --- a/Core/Commands/Mediator/IMediatorCommandHandler.cs +++ /dev/null @@ -1,8 +0,0 @@ -using MediatR; - -namespace Core.Commands.Mediator; - -public interface IMediatorCommandHandler: IRequestHandler - where T : ICommand -{ -} diff --git a/Core/Commands/Mediator/MediatorCommandBus.cs b/Core/Commands/Mediator/MediatorCommandBus.cs deleted file mode 100644 index 1773f1aa0..000000000 --- a/Core/Commands/Mediator/MediatorCommandBus.cs +++ /dev/null @@ -1,18 +0,0 @@ -using MediatR; - -namespace Core.Commands.Mediator; - -public class MediatorCommandBus: IMediatorCommandBus -{ - private readonly IMediator mediator; - - public MediatorCommandBus(IMediator mediator) - { - this.mediator = mediator; - } - - public Task Send(TCommand command) where TCommand : ICommand - { - return mediator.Send(command); - } -} diff --git a/Core/Config.cs b/Core/Config.cs index c08f3e5b4..c64d2b45e 100644 --- a/Core/Config.cs +++ b/Core/Config.cs @@ -4,7 +4,6 @@ using Core.OpenTelemetry; using Core.Queries; using Core.Requests; -using MediatR; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -14,13 +13,11 @@ public static class Config { public static IServiceCollection AddCoreServices(this IServiceCollection services) { - // TODO: Remove MediatR services .AddSingleton() - .AddMediatR() - .AddScoped() .AddEventBus() - .AddCommandBus(); + .AddCommandBus() + .AddQueryBus(); services.TryAddScoped(); @@ -28,11 +25,4 @@ public static IServiceCollection AddCoreServices(this IServiceCollection service return services; } - - private static IServiceCollection AddMediatR(this IServiceCollection services) - { - return services - .AddScoped() - .AddTransient(sp => sp.GetRequiredService!); - } } diff --git a/Core/Core.csproj b/Core/Core.csproj index 882aed399..6bf96e3d4 100644 --- a/Core/Core.csproj +++ b/Core/Core.csproj @@ -5,7 +5,6 @@ - diff --git a/Core/Events/Mediator/IEvent.cs b/Core/Events/Mediator/IEvent.cs deleted file mode 100644 index b2b602593..000000000 --- a/Core/Events/Mediator/IEvent.cs +++ /dev/null @@ -1,7 +0,0 @@ -using MediatR; - -namespace Core.Events.Mediator; - -public interface IEvent: INotification -{ -} diff --git a/Core/Events/Mediator/IMediatorEventHandler.cs b/Core/Events/Mediator/IMediatorEventHandler.cs deleted file mode 100644 index 0a01dcb17..000000000 --- a/Core/Events/Mediator/IMediatorEventHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using MediatR; -using Microsoft.Extensions.DependencyInjection; - -namespace Core.Events.Mediator; - -public interface IMediatorEventHandler: INotificationHandler - where TEvent : IEvent -{ -} - -public static class MediatorEventHandlerExtensions -{ - public static IServiceCollection AddMediatorEventHandler( - this IServiceCollection services - ) - where TEvent : IEvent - where TEventHandler : class, IMediatorEventHandler - { - return services.AddTransient() - .AddTransient>(sp => sp.GetRequiredService()) - .AddTransient>(sp => sp.GetRequiredService()); - } -} diff --git a/Core/Events/Mediator/MediatorEventBus.cs b/Core/Events/Mediator/MediatorEventBus.cs deleted file mode 100644 index 982c1aea7..000000000 --- a/Core/Events/Mediator/MediatorEventBus.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MediatR; - -namespace Core.Events.Mediator; - -public interface IEventBus -{ - Task Publish(IEvent @event, CancellationToken ct); - Task Publish(IEvent[] events, CancellationToken ct); -} - -public class MediatorEventBus: IEventBus -{ - private readonly IMediator mediator; - - public MediatorEventBus( - IMediator mediator - ) - { - this.mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - } - - public async Task Publish(IEvent[] events, CancellationToken ct) - { - foreach (var @event in events) - { - await Publish(@event, ct); - } - } - - public async Task Publish(IEvent @event, CancellationToken ct) - { - await mediator.Publish(@event, ct); - } -} diff --git a/Core/OpenTelemetry/TelemetryTags.cs b/Core/OpenTelemetry/TelemetryTags.cs index 3b08d5705..253adc1aa 100644 --- a/Core/OpenTelemetry/TelemetryTags.cs +++ b/Core/OpenTelemetry/TelemetryTags.cs @@ -12,6 +12,11 @@ public static class CommandHandling public const string Command = $"{ActivitySourceProvider.DefaultSourceName}.command"; } + public static class QueryHandling + { + public const string Query = $"{ActivitySourceProvider.DefaultSourceName}.query"; + } + public static class EventHandling { public const string Event = $"{ActivitySourceProvider.DefaultSourceName}.event"; diff --git a/Core/Queries/Config.cs b/Core/Queries/Config.cs index 982e334f7..dacaf82a7 100644 --- a/Core/Queries/Config.cs +++ b/Core/Queries/Config.cs @@ -1,5 +1,4 @@ -using MediatR; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace Core.Queries; @@ -8,11 +7,10 @@ public static class Config public static IServiceCollection AddQueryHandler( this IServiceCollection services ) - where TQuery : IQuery + where TQuery : notnull where TQueryHandler : class, IQueryHandler { return services.AddTransient() - .AddTransient>(sp => sp.GetRequiredService()) .AddTransient>(sp => sp.GetRequiredService()); } -} \ No newline at end of file +} diff --git a/Core/Queries/IQuery.cs b/Core/Queries/IQuery.cs deleted file mode 100644 index c0579d1e0..000000000 --- a/Core/Queries/IQuery.cs +++ /dev/null @@ -1,7 +0,0 @@ -using MediatR; - -namespace Core.Queries; - -public interface IQuery: IRequest -{ -} \ No newline at end of file diff --git a/Core/Queries/IQueryBus.cs b/Core/Queries/IQueryBus.cs index d0ae4bdee..b6ae27cad 100644 --- a/Core/Queries/IQueryBus.cs +++ b/Core/Queries/IQueryBus.cs @@ -2,5 +2,6 @@ namespace Core.Queries; public interface IQueryBus { - Task Send(TQuery query) where TQuery : IQuery; -} \ No newline at end of file + Task Query(TQuery query, CancellationToken ct = default) + where TQuery : notnull; +} diff --git a/Core/Queries/IQueryHandler.cs b/Core/Queries/IQueryHandler.cs index 251af3815..3eaae3f4f 100644 --- a/Core/Queries/IQueryHandler.cs +++ b/Core/Queries/IQueryHandler.cs @@ -1,8 +1,7 @@ -using MediatR; - namespace Core.Queries; -public interface IQueryHandler: IRequestHandler - where TQuery : IQuery +public interface IQueryHandler + where TQuery : notnull { -} \ No newline at end of file + Task Handle(TQuery request, CancellationToken cancellationToken); +} diff --git a/Core/Queries/QueryBus.cs b/Core/Queries/QueryBus.cs index b9db6ba4f..72edd7c60 100644 --- a/Core/Queries/QueryBus.cs +++ b/Core/Queries/QueryBus.cs @@ -1,18 +1,61 @@ -using MediatR; +using Core.OpenTelemetry; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Polly; namespace Core.Queries; public class QueryBus: IQueryBus { - private readonly IMediator mediator; + private readonly IServiceProvider serviceProvider; + private readonly AsyncPolicy retryPolicy; + private readonly IActivityScope activityScope; - public QueryBus(IMediator mediator) + public QueryBus( + IServiceProvider serviceProvider, + IActivityScope activityScope, + AsyncPolicy retryPolicy + ) { - this.mediator = mediator; + this.serviceProvider = serviceProvider; + this.retryPolicy = retryPolicy; + this.activityScope = activityScope; } - public Task Send(TQuery query) where TQuery : IQuery + public Task Query(TQuery query, CancellationToken ct = default) + where TQuery : notnull { - return mediator.Send(query); + var queryHandler = + serviceProvider.GetService>() + ?? throw new InvalidOperationException($"Unable to find handler for Query '{query.GetType().Name}'"); + + var queryName = typeof(TQuery).Name; + var activityName = $"{queryHandler.GetType().Name}/{queryName}"; + + return activityScope.Run( + activityName, + (_, token) => retryPolicy.ExecuteAsync(c => queryHandler.Handle(query, c), token), + new StartActivityOptions { Tags = {{ TelemetryTags.QueryHandling.Query, queryName }}}, + ct + ); + } +} + +public static class EventBusExtensions +{ + public static IServiceCollection AddQueryBus(this IServiceCollection services, AsyncPolicy? asyncPolicy = null) + { + services + .AddScoped(sp => + new QueryBus( + sp, + sp.GetRequiredService(), + asyncPolicy ?? Policy.NoOpAsync() + )) + .TryAddScoped(sp => + sp.GetRequiredService() + ); + + return services; } -} \ No newline at end of file +} diff --git a/EventSourcing.Integration.Tests/EventSourcing.Integration.Tests.csproj b/EventSourcing.Integration.Tests/EventSourcing.Integration.Tests.csproj index 7bd2f33c7..675ca67ea 100644 --- a/EventSourcing.Integration.Tests/EventSourcing.Integration.Tests.csproj +++ b/EventSourcing.Integration.Tests/EventSourcing.Integration.Tests.csproj @@ -14,7 +14,6 @@ - all diff --git a/EventSourcing.NetCore.sln b/EventSourcing.NetCore.sln index 860fcb53c..dc917d097 100644 --- a/EventSourcing.NetCore.sln +++ b/EventSourcing.NetCore.sln @@ -22,10 +22,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Tests", "Core.Tests\Core.Tests.csproj", "{E1B97A7B-97C3-4C14-9BE6-ACE0AF45CE61}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediatR.Tests", "MediatR.Tests\MediatR.Tests.csproj", "{E942A5A1-2B6E-41A0-8445-C5A38D955611}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CQRS.Tests", "CQRS.Tests\CQRS.Tests.csproj", "{7532F3EB-D50F-490C-A1E1-4E0B882281FD}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventSourcing.Integration.Tests", "EventSourcing.Integration.Tests\EventSourcing.Integration.Tests.csproj", "{215691EC-51FB-4BD2-A46C-396094727054}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{821D8306-C110-45AB-BDF7-AA80FDA942CE}" @@ -352,14 +348,6 @@ Global {E1B97A7B-97C3-4C14-9BE6-ACE0AF45CE61}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1B97A7B-97C3-4C14-9BE6-ACE0AF45CE61}.Release|Any CPU.ActiveCfg = Release|Any CPU {E1B97A7B-97C3-4C14-9BE6-ACE0AF45CE61}.Release|Any CPU.Build.0 = Release|Any CPU - {E942A5A1-2B6E-41A0-8445-C5A38D955611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E942A5A1-2B6E-41A0-8445-C5A38D955611}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E942A5A1-2B6E-41A0-8445-C5A38D955611}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E942A5A1-2B6E-41A0-8445-C5A38D955611}.Release|Any CPU.Build.0 = Release|Any CPU - {7532F3EB-D50F-490C-A1E1-4E0B882281FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7532F3EB-D50F-490C-A1E1-4E0B882281FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7532F3EB-D50F-490C-A1E1-4E0B882281FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7532F3EB-D50F-490C-A1E1-4E0B882281FD}.Release|Any CPU.Build.0 = Release|Any CPU {215691EC-51FB-4BD2-A46C-396094727054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {215691EC-51FB-4BD2-A46C-396094727054}.Debug|Any CPU.Build.0 = Debug|Any CPU {215691EC-51FB-4BD2-A46C-396094727054}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -774,8 +762,6 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {E1B97A7B-97C3-4C14-9BE6-ACE0AF45CE61} = {107B18E3-65C8-4A6C-976D-7EEED6A6D318} - {E942A5A1-2B6E-41A0-8445-C5A38D955611} = {107B18E3-65C8-4A6C-976D-7EEED6A6D318} - {7532F3EB-D50F-490C-A1E1-4E0B882281FD} = {107B18E3-65C8-4A6C-976D-7EEED6A6D318} {215691EC-51FB-4BD2-A46C-396094727054} = {107B18E3-65C8-4A6C-976D-7EEED6A6D318} {F755E316-140C-4A73-9586-06860521C1B6} = {A8E25331-55E9-4D1A-87A4-136EC4D2A4B5} {3C628C0A-71AD-4C41-9977-A33F89C0751B} = {A7186B6B-D56D-4AEF-B6B7-FAA827764C34} diff --git a/MediatR.Tests/Initialization/Initialization.cs b/MediatR.Tests/Initialization/Initialization.cs deleted file mode 100644 index 913f02737..000000000 --- a/MediatR.Tests/Initialization/Initialization.cs +++ /dev/null @@ -1,36 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace MediatR.Tests.Initialization; - -public class Initialization -{ - private static class ServiceLocator - { - private static readonly Dictionary> Services = new Dictionary>(); - - public static void Register(Type type, params object[] implementations) - => Services.Add(type, implementations.ToList()); - - public static List Get(Type type) - { - return Services[type]; - } - } - - [Fact] - public void GivenProperParams_WhenObjectIsCreated_ThenIsCreatedProperly() - { - var ex = Record.Exception(() => - { - //Given - //When - var mediator = new Mediator(type => ServiceLocator.Get(type).Single()); - - mediator.Should().NotBeNull(); - }); - - //Then - ex.Should().BeNull(); - } -} diff --git a/MediatR.Tests/MediatR.Tests.csproj b/MediatR.Tests/MediatR.Tests.csproj deleted file mode 100644 index d961fa6e9..000000000 --- a/MediatR.Tests/MediatR.Tests.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net7.0 - - - - - PreserveNewest - - - PreserveNewest - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - diff --git a/MediatR.Tests/Publishing/MoreThanOneHandler.cs b/MediatR.Tests/Publishing/MoreThanOneHandler.cs deleted file mode 100644 index a9b0ea9bd..000000000 --- a/MediatR.Tests/Publishing/MoreThanOneHandler.cs +++ /dev/null @@ -1,84 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace MediatR.Tests.Publishing; - -public class MoreThanOneHandler -{ - public class ServiceLocator - { - private readonly Dictionary> services = new Dictionary>(); - - public void Register(Type type, params object[] implementations) - => services.Add(type, implementations.ToList()); - - public List Get(Type type) - { - return services[type]; - } - } - - public class IssuesList - { - public List Issues { get; } - - public IssuesList() - { - Issues = new List(); - } - } - - public class IssueCreated: INotification - { - public string IssueName { get; } - - public IssueCreated(string issueName) - { - IssueName = issueName; - } - } - - public class IssueCreatedHandler: INotificationHandler - { - private readonly IssuesList issuesList; - - public IssueCreatedHandler(IssuesList issuesList) - { - this.issuesList = issuesList; - } - - public Task Handle(IssueCreated @event, CancellationToken cancellationToken = default(CancellationToken)) - { - issuesList.Issues.Add(@event.IssueName); - return Task.CompletedTask; - } - } - - private readonly IMediator mediator; - private readonly IssuesList issuesList = new IssuesList(); - - public MoreThanOneHandler() - { - var eventHandler = new IssueCreatedHandler(issuesList); - - var serviceLocator = new ServiceLocator(); - serviceLocator.Register(typeof(IEnumerable>), - new object[] { new List> { eventHandler, eventHandler } }); - - mediator = new Mediator(type => serviceLocator.Get(type).Single()); - } - - [Fact] - public async Task GivenTwoHandlersForOneEvent_WhenPublishMethodIsBeingCalled_ThenTwoHandlersAreBeingCalled() - { - //Given - var @event = new IssueCreated("cleaning"); - - //When - await mediator.Publish(@event); - - //Then - issuesList.Issues.Count.Should().Be(2); - issuesList.Issues.Should().BeEquivalentTo("cleaning", "cleaning"); - } -} diff --git a/MediatR.Tests/Publishing/NoHandlers.cs b/MediatR.Tests/Publishing/NoHandlers.cs deleted file mode 100644 index 0ead44385..000000000 --- a/MediatR.Tests/Publishing/NoHandlers.cs +++ /dev/null @@ -1,59 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace MediatR.Tests.Publishing; - -public class NoHandlers -{ - public class ServiceLocator - { - private readonly Dictionary> services = new Dictionary>(); - - public void Register(Type type, params object[] implementations) - => services.Add(type, implementations.ToList()); - - public List Get(Type type) - { - return services[type]; - } - } - - public class IssuesList - { - public List Issues { get; } - - public IssuesList() - { - Issues = new List(); - } - } - - public class IssueCreated: INotification - { - public string IssueName { get; } - - public IssueCreated(string issueName) - { - IssueName = issueName; - } - } - - [Fact] - public async Task GivenNonRegisteredQueryHandler_WhenPublishMethodIsBeingCalled_ThenThrowsAnError() - { - var ex = await Record.ExceptionAsync(async () => - { - //Given - var serviceLocator = new ServiceLocator(); - var mediator = new Mediator(type => serviceLocator.Get(type).Single()); - - var @event = new IssueCreated("cleaning"); - - //When - await mediator.Publish(@event); - }); - - //Then - ex.Should().NotBeNull(); - } -} diff --git a/MediatR.Tests/Publishing/SingleHandler.cs b/MediatR.Tests/Publishing/SingleHandler.cs deleted file mode 100644 index f6cb0ee58..000000000 --- a/MediatR.Tests/Publishing/SingleHandler.cs +++ /dev/null @@ -1,85 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace MediatR.Tests.Publishing; - -public class SingleHandler -{ - public class ServiceLocator - { - private readonly Dictionary> services = new Dictionary>(); - - public void Register(Type type, params object[] implementations) - => services.Add(type, implementations.ToList()); - - public List Get(Type type) - { - return services[type]; - } - } - - public class IssuesList - { - public List Issues { get; } - - public IssuesList() - { - Issues = new List(); - } - } - - public class IssueCreated: INotification - { - public string IssueName { get; } - - public IssueCreated(string issueName) - { - IssueName = issueName; - } - } - - public class IssueCreatedHandler: INotificationHandler - { - private readonly IssuesList issuesList; - - public IssueCreatedHandler(IssuesList issuesList) - { - this.issuesList = issuesList; - } - - public Task Handle(IssueCreated @event, CancellationToken cancellationToken = default) - { - issuesList.Issues.Add(@event.IssueName); - return Task.CompletedTask; - } - } - - private readonly IMediator mediator; - private readonly IssuesList issuesList = new IssuesList(); - - public SingleHandler() - { - var notificationHandler = new IssueCreatedHandler(issuesList); - - var serviceLocator = new ServiceLocator(); - - serviceLocator.Register(typeof(IEnumerable>), - new object[] { new List> { notificationHandler } }); - - mediator = new Mediator(type => serviceLocator.Get(type).Single()); - } - - [Fact] - public async Task GivenRegisteredAsynchronousRequestHandler_WhenPublishMethodIsBeingCalled_ThenReturnsProperResult() - { - //Given - var @event = new IssueCreated("cleaning"); - - //When - await mediator.Publish(@event); - - //Then - issuesList.Issues.Should().HaveCount(1); - issuesList.Issues.Should().BeEquivalentTo("cleaning"); - } -} diff --git a/MediatR.Tests/Sending/MoreThanOneHandler.cs b/MediatR.Tests/Sending/MoreThanOneHandler.cs deleted file mode 100644 index 9590d1dd7..000000000 --- a/MediatR.Tests/Sending/MoreThanOneHandler.cs +++ /dev/null @@ -1,85 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace MediatR.Tests.Sending; - -public class MoreThanOneHandler -{ - public class ServiceLocator - { - private readonly Dictionary> services = new(); - - public void Register(Type type, params object[] implementations) - => services.Add(type, implementations.ToList()); - - public List Get(Type type) - { - return services[type]; - } - } - - public class IssuesList - { - public List Issues { get; } - - public IssuesList(params string[] issues) - { - Issues = issues.ToList(); - } - } - - public class CreateIssueCommand: IRequest - { - public string IssueName { get; } - - public CreateIssueCommand(string issueName) - { - IssueName = issueName; - } - } - - public class CreateIssueCommandHandler: IRequestHandler - { - private readonly IssuesList issuesList; - - public CreateIssueCommandHandler(IssuesList issuesList) - { - this.issuesList = issuesList; - } - - public Task Handle(CreateIssueCommand command, CancellationToken cancellationToken = default(CancellationToken)) - { - issuesList.Issues.Add(command.IssueName); - return Unit.Task; - } - } - - private readonly IMediator mediator; - private readonly IssuesList issuesList = new IssuesList(); - - public MoreThanOneHandler() - { - var commandHandler = new CreateIssueCommandHandler(issuesList); - - var serviceLocator = new ServiceLocator(); - serviceLocator.Register(typeof(IRequestHandler), commandHandler, commandHandler); - //Registration needed internally by MediatR - serviceLocator.Register(typeof(IEnumerable>), new List>()); - - mediator = new Mediator(type => serviceLocator.Get(type).First()); - } - - [Fact] - public async Task GivenTwoHandlersForOneCommand_WhenSendMethodIsBeingCalled_ThenOnlyFIrstHandlersIsBeingCalled() - { - //Given - var query = new CreateIssueCommand("cleaning"); - - //When - await mediator.Send(query); - - //Then - issuesList.Issues.Count.Should().Be(1); - issuesList.Issues.Should().BeEquivalentTo("cleaning"); - } -} diff --git a/MediatR.Tests/Sending/NoHandlers.cs b/MediatR.Tests/Sending/NoHandlers.cs deleted file mode 100644 index 42d98b2c1..000000000 --- a/MediatR.Tests/Sending/NoHandlers.cs +++ /dev/null @@ -1,59 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace MediatR.Tests.Sending; - -public class NoHandlers -{ - public class ServiceLocator - { - private readonly Dictionary> services = new(); - - public void Register(Type type, params object[] implementations) - => services.Add(type, implementations.ToList()); - - public List Get(Type type) - { - return services[type]; - } - } - - public class IssuesList - { - public List Issues { get; } - - public IssuesList(params string[] issues) - { - Issues = issues.ToList(); - } - } - - public class GetIssuesNamesQuery: IRequest> - { - public string Filter { get; } - - public GetIssuesNamesQuery(string filter) - { - Filter = filter; - } - } - - [Fact] - public async Task GivenNonRegisteredQueryHandler_WhenSendMethodIsBeingCalled_ThenThrowsAnError() - { - var ex = await Record.ExceptionAsync(async () => - { - //Given - var serviceLocator = new ServiceLocator(); - var mediator = new Mediator(type => serviceLocator.Get(type).Single()); - - var query = new GetIssuesNamesQuery("cleaning"); - - //When - var result = await mediator.Send(query); - }); - - //Then - ex.Should().NotBeNull(); - } -} diff --git a/MediatR.Tests/Sending/SingleHandler.cs b/MediatR.Tests/Sending/SingleHandler.cs deleted file mode 100644 index 2b8d04221..000000000 --- a/MediatR.Tests/Sending/SingleHandler.cs +++ /dev/null @@ -1,86 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace MediatR.Tests.Sending; - -public class SingleHandler -{ - public class ServiceLocator - { - private readonly Dictionary> services = new(); - - public void Register(Type type, params object[] implementations) - => services.Add(type, implementations.ToList()); - - public List Get(Type type) - { - return services[type]; - } - } - - public class IssuesList - { - public List Issues { get; } - - public IssuesList(params string[] issues) - { - Issues = issues.ToList(); - } - } - - public class GetIssuesNamesQuery: IRequest> - { - public string Filter { get; } - - public GetIssuesNamesQuery(string filter) - { - Filter = filter; - } - } - - public class GetIssuesNamesQueryHandler: IRequestHandler> - { - private readonly IssuesList issuesList; - - public GetIssuesNamesQueryHandler(IssuesList issuesList) - { - this.issuesList = issuesList; - } - - public Task> Handle(GetIssuesNamesQuery query, CancellationToken cancellationToken = default) - { - return Task.Run(() => issuesList.Issues - .Where(taskName => taskName.ToLower().Contains(query.Filter.ToLower())) - .ToList(), cancellationToken); - } - } - - private readonly IMediator mediator; - - public SingleHandler() - { - var queryHandler = new GetIssuesNamesQueryHandler( - new IssuesList("Cleaning main room", "Writing blog", "cleaning kitchen")); - - var serviceLocator = new ServiceLocator(); - serviceLocator.Register(typeof(IRequestHandler>), queryHandler); - //Registration needed internally by MediatR - serviceLocator.Register(typeof(IEnumerable>>), new List>>()); - - mediator = new Mediator(type => serviceLocator.Get(type).Single()); - } - - [Fact] - public async Task GivenRegisteredAsynchronousRequestHandler_WhenSendMethodIsBeingCalled_ThenReturnsProperResult() - { - //Given - var query = new GetIssuesNamesQuery("cleaning"); - - //When - var result = await mediator.Send(query); - - //Then - result.Should().HaveCount(2); - result.Should().BeEquivalentTo("Cleaning main room", "cleaning kitchen"); - } -} diff --git a/MediatR.Tests/xunit.runner.json b/MediatR.Tests/xunit.runner.json deleted file mode 100644 index edb232128..000000000 --- a/MediatR.Tests/xunit.runner.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parallelizeTestCollections": false -} \ No newline at end of file diff --git a/README.md b/README.md index 3b7c36aec..d1275b29b 100644 --- a/README.md +++ b/README.md @@ -42,31 +42,29 @@ Tutorial, practical samples and other resources about Event Sourcing in .NET. Se - [7.2 Build your own Event Store](#72-build-your-own-event-store) - [8. Articles](#8-articles) - [9. Event Store - Marten](#9-event-store---marten) - - [10. Message Bus (for processing Commands, Queries, Events) - MediatR](#10-message-bus-for-processing-commands-queries-events---mediatr) - - [11. CQRS (Command Query Responsibility Separation)](#11-cqrs-command-query-responsibility-separation) - - [12. NuGet packages to help you get started.](#12-nuget-packages-to-help-you-get-started) - - [13. Other resources](#13-other-resources) - - [13.1 Introduction](#131-introduction) - - [13.2 Event Sourcing on production](#132-event-sourcing-on-production) - - [13.3 Projections](#133-projections) - - [13.4 Snapshots](#134-snapshots) - - [13.5 Versioning](#135-versioning) - - [13.6 Storage](#136-storage) - - [13.7 Design & Modeling](#137-design--modeling) - - [13.8 GDPR](#138-gdpr) - - [13.9 Conflict Detection](#139-conflict-detection) - - [13.10 Functional programming](#1310-functional-programming) - - [13.12 Testing](#1312-testing) - - [13.13 CQRS](#1313-cqrs) - - [13.14 Tools](#1314-tools) - - [13.15 Event processing](#1315-event-processing) - - [13.16 Distributed processes](#1316-distributed-processes) - - [13.17 Domain Driven Design](#1317-domain-driven-design) - - [13.18 Whitepapers](#1318-whitepapers) - - [13.19 This is NOT Event Sourcing (but Event Streaming)](#1319-this-is-not-event-sourcing-but-event-streaming) - - [13.20 Event Sourcing Concerns](#1320-event-sourcing-concerns) - - [13.21 Architecture Weekly](#1321-architecture-weekly) - + - [10. CQRS (Command Query Responsibility Separation)](#10-cqrs-command-query-responsibility-separation) + - [11. NuGet packages to help you get started.](#11-nuget-packages-to-help-you-get-started) + - [12. Other resources](#12-other-resources) + - [12.1 Introduction](#121-introduction) + - [12.2 Event Sourcing on production](#122-event-sourcing-on-production) + - [12.3 Projections](#123-projections) + - [12.4 Snapshots](#124-snapshots) + - [12.5 Versioning](#125-versioning) + - [12.6 Storage](#126-storage) + - [12.7 Design & Modeling](#127-design--modeling) + - [12.8 GDPR](#128-gdpr) + - [12.9 Conflict Detection](#129-conflict-detection) + - [12.10 Functional programming](#1210-functional-programming) + - [12.12 Testing](#1212-testing) + - [12.13 CQRS](#1213-cqrs) + - [12.14 Tools](#1214-tools) + - [12.15 Event processing](#1215-event-processing) + - [12.16 Distributed processes](#1216-distributed-processes) + - [12.17 Domain Driven Design](#1217-domain-driven-design) + - [12.18 Whitepapers](#1218-whitepapers) + - [12.19 This is NOT Event Sourcing (but Event Streaming)](#1219-this-is-not-event-sourcing-but-event-streaming) + - [12.20 Event Sourcing Concerns](#1220-event-sourcing-concerns) + - [12.21 Architecture Weekly](#1221-architecture-weekly) ## 1. Event Sourcing @@ -615,9 +613,8 @@ docker-compose up 1. [Marten](https://martendb.io/) - Event Store and Read Models 2. [EventStoreDB](https://eventstore.com) - Event Store -3. [MediatR](https://github.com/jbogard/MediatR) - Internal In-Memory Message Bus (for processing Commands, Queries, Events) -4. [Kafka](https://kafka.apache.org/) - External Durable Message Bus to integrate services -5. [ElasticSearch](https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/nest-getting-started.html) - Read Models +3. [Kafka](https://kafka.apache.org/) - External Durable Message Bus to integrate services +4. [ElasticSearch](https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/nest-getting-started.html) - Read Models ## 6. Samples @@ -861,25 +858,12 @@ Read also more on the **Event Sourcing** and **CQRS** topics in my [blog](https: - **[Projection of single stream](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/Marten.Integration.Tests/EventStore/Projections/AggregationProjectionsTest.cs)** - **[Multitenancy per schema](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/Marten.Integration.Tests/Tenancy/TenancyPerSchema.cs)** -## 10. Message Bus (for processing Commands, Queries, Events) - MediatR - -- **[Initialization](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/MediatR.Tests/Initialization/Initialization.cs)** - MediatR uses services locator pattern to find a proper handler for the message type. -- **Sending Messages** - finds and uses the first registered handler for the message type. It could be used for queries (when we need to return values), commands (when we acting). - - **[No Handlers](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/MediatR.Tests/Sending/NoHandlers.cs)** - when MediatR doesn't find proper handler it throws an exception. - - **[Single Handler](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/MediatR.Tests/Sending/SingleHandler.cs)** - by implementing IRequestHandler we're deciding that this handler should be run asynchronously with other async handlers (so we don't wait for the previous handler to finish its work). - - **[More Than One Handler](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/MediatR.Tests/Sending/MoreThanOneHandler.cs)** - when there is more than one handler registered MediatR takes only one ignoring others when Send method is being called. -- **Publishing Messages** - finds and uses all registered handlers for the message type. It's good for processing events. - - **[No Handlers](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/MediatR.Tests/Publishing/NoHandlers.cs)** - when MediatR doesn't find proper handler it throws an exception - - **[Single Handler](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/MediatR.Tests/Publishing/SingleHandler.cs)** - by implementing INotificationHandler we're deciding that this handler should be run asynchronously with other async handlers (so we don't wait for the previous handler to finish its work) - - **[More Than One Handler](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/MediatR.Tests/Publishing/MoreThanOneHandler.cs)** - when there is more than one handler registered MediatR takes all of them when calling Publish method -- Pipeline (to be defined) - -## 11. CQRS (Command Query Responsibility Separation) +## 10. CQRS (Command Query Responsibility Separation) - **[Command handling](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/CQRS.Tests/Commands/Commands.cs)** - **[Query handling](https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/CQRS.Tests/Queries/Queries.cs)** -## 12. NuGet packages to help you get started. +## 11. NuGet packages to help you get started. I gathered and generalized all of the practices used in this tutorial/samples in Nuget Packages maintained by me [GoldenEye Framework](https://github.com/oskardudycz/GoldenEye). See more in: @@ -892,9 +876,9 @@ See more in: `dotnet add package GoldenEye.Marten` -## 13. Other resources +## 12. Other resources -### 13.1 Introduction +### 12.1 Introduction - 📝 [Event Store - A Beginner's Guide to Event Sourcing](https://www.eventstore.com/event-sourcing) - 🎞 [Greg Young - CQRS & Event Sourcing](https://youtube.com/watch?v=JHGkaShoyNs) - 📰 [Lorenzo Nicora - A visual introduction to event sourcing and cqrs](https://www.slideshare.net/LorenzoNicora/a-visual-introduction-to-event-sourcing-and-cqrs) @@ -921,7 +905,7 @@ See more in: -### 13.2 Event Sourcing on production +### 12.2 Event Sourcing on production - 🎞 [Alexey Zimarev - Event Sourcing in Production](https://youtu.be/DDefPUCB9ao?t=238) - 📝 [Leo Gorodinski - Scaling Event-Sourcing at Jet](https://medium.com/@eulerfx/scaling-event-sourcing-at-jet-9c873cac33b8) - 📝 [EventStoreDB - Customers' case studies](https://www.eventstore.com/case-studies) @@ -944,23 +928,23 @@ See more in: - 📝 [Dennis Doomen - A recipe for gradually migrating from CRUD to Event Sourcing](https://www.eventstore.com/blog/a-recipe-for-gradually-migrating-from-crud-to-event-sourcing) - 🎞 [Nat Pryce - Mistakes made adopting event sourcing (and how we recovered)](https://www.youtube.com/watch?v=osk0ZBdBbx4) -### 13.3 Projections +### 12.3 Projections - 📝 [Alexey Zimarev - Projections in Event Sourcing](https://zimarev.com/blog/event-sourcing/projections/) - 📝 [Rinat Abdulin - Event Sourcing - Projections](https://abdullin.com/post/event-sourcing-projections/) - 🎞 [Derek Comartin - Projections in Event Sourcing: Build ANY model you want!](https://www.youtube.com/watch?v=bTRjO6JK4Ws) -### 13.4 Snapshots +### 12.4 Snapshots - 📝 [Kacper Gunia - Event Sourcing: Snapshotting](https://domaincentric.net/blog/event-sourcing-snapshotting) - 🎞 [Derek Comartin - Event Sourcing: Rehydrating Aggregates with Snapshots](https://www.youtube.com/watch?v=eAIkomEid1Y) -### 13.5 Versioning +### 12.5 Versioning - 📝 [Greg Young - Versioning in an Event Sourced System](https://leanpub.com/esversioning/read) - 📝 [Kacper Gunia - Event Sourcing: Snapshotting](https://domaincentric.net/blog/event-sourcing-snapshotting) - 📝 [M. Overeem, M. Spoor - The dark side of event sourcing: Managing data conversion](https://www.researchgate.net/publication/315637858_The_dark_side_of_event_sourcing_Managing_data_conversion) - 📝 [Savvas Kleanthous - Event immutability and dealing with change](https://www.eventstore.com/blog/event-immutability-and-dealing-with-change) - 📝 [Versioning in an Event Sourced System](http://blog.approache.com/2019/02/versioning-in-event-sourced-system-tldr_10.html?m=1) -### 13.6 Storage +### 12.6 Storage - 📝 [Greg Young - Building an Event Storage](https://cqrs.wordpress.com/documents/building-event-storage/) - 📝 [Adam Warski - Implementing event sourcing using a relational database](https://softwaremill.com/implementing-event-sourcing-using-a-relational-database/) - 🎞 [Greg Young - How an EventStore actually works](https://www.youtube.com/watch?v=YUjO1wM0PZM) @@ -969,7 +953,7 @@ See more in: - 📝 [AWS Architecture Blog - How The Mill Adventure Implemented Event Sourcing at Scale Using DynamoDB](https://aws.amazon.com/blogs/architecture/how-the-mill-adventure-implemented-event-sourcing-at-scale-using-dynamodb/) - 🎞 [Sander Molenkamp: Practical CQRS and Event Sourcing on Azure](https://www.youtube.com/watch?v=3XcB-5CrRe8) -### 13.7 Design & Modeling +### 12.7 Design & Modeling - 📝 [Mathias Verraes - DDD and Messaging Architectures](http://verraes.net/2019/05/ddd-msg-arch/) - 📝 [David Boike - Putting your events on a diet](https://particular.net/blog/putting-your-events-on-a-diet) - 🎞 [Thomas Pierrain - As Time Goes By… (a Bi-temporal Event Sourcing story)](https://youtube.com/watch?v=xzekp1RuZbM) @@ -981,21 +965,21 @@ See more in: - 📝 [Event Modeling](https://eventmodeling.org/posts/what-is-event-modeling/) - 📝 [Wojciech Suwała - Building Microservices On .NET Core – Part 5 Marten An Ideal Repository For Your Domain Aggregates](https://altkomsoftware.pl/en/blog/building-microservices-domain-aggregates/) -### 13.8 GDPR +### 12.8 GDPR - 📝 [Michiel Rook - Event sourcing and the GDPR: a follow-up](https://www.michielrook.nl/2017/11/event-sourcing-gdpr-follow-up/) -### 13.9 Conflict Detection +### 12.9 Conflict Detection - 🎞 [James Geall - Conflict Detection and Resolution in an EventSourced System](https://www.youtube.com/watch?v=-zaa6FUYIQM) - 🎞 [Lightbend - Data modelling for Replicated Event Sourcing](https://www.youtube.com/watch?v=8PnJxTlOP6o) - 📰 [Bartosz Sypytkowski - Collaborative Event Sourcing](https://www.slideshare.net/BartoszSypytkowski1/collaborative-replication) -### 13.10 Functional programming +### 12.10 Functional programming - 📝 [Jérémie Chassaing - Functional Programming and Event Sourcing](https://www.youtube.com/watch?v=kgYGMVDHQHs) -### 13.12 Testing +### 12.12 Testing - 🎞 [N. Rauch & A. Bailly - From Front to Back: Homomorphic Event Sourcing](https://www.youtube.com/watch?v=KyOvBQ87aP4) -### 13.13 CQRS +### 12.13 CQRS - 📝 [Greg Young - CQRS](https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf) - 📝 [Jimmy Bogard - CQRS and REST: the perfect match](https://lostechies.com/jimmybogard/2016/06/01/cqrs-and-rest-the-perfect-match/) - 📝 [Mark Seemann - CQS versus server-generated IDs](http://blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids/) @@ -1005,7 +989,7 @@ See more in: - 🎞 [Udi Dahan - CQRS – but different](https://vimeo.com/131199089) - 📝 [Greg Young - CQRS, Task Based UIs, Event Sourcing agh!](http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/) -### 13.14 Tools +### 12.14 Tools - 🛠️ [Marten - .NET Transactional Document DB and Event Store on PostgreSQL](https://eventuous.dev/) - 🛠️ [EventStoreDB - The stream database built for Event Sourcing ](https://developers.eventstore.com/) - 🛠️ [GoldenEye - The CQRS flavoured framework that will speed up your WebAPI and Microservices development ](https://eventuous.dev/) @@ -1013,7 +997,7 @@ See more in: - 🛠️ [SQLStreamStore - Stream Store library targeting RDBMS based implementations for .NET ](https://github.com/SQLStreamStore/SQLStreamStore) - 🛠️ [Equinox - .NET Event Sourcing library with CosmosDB, EventStoreDB, SqlStreamStore and integration test backends](https://github.com/jet/equinox) -### 13.15 Event processing +### 12.15 Event processing - 📝 [Kamil Grzybek - The Outbox Pattern](http://www.kamilgrzybek.com/design/the-outbox-pattern/) - 🎞 [Dev Mentors - Inbox & Outbox pattern - transactional message processing](https://www.youtube.com/watch?v=ebyR5RPKciw) - 📝 [Jeremy D. Miller - Jasper's "Outbox" Pattern Support](https://jeremydmiller.com/2018/04/16/jaspers-outbox-pattern-support/) @@ -1022,7 +1006,7 @@ See more in: - 📝 [NServiceBus - Outbox](https://docs.particular.net/nservicebus/outbox/) - 📝 [Alvaro Herrera - Implement SKIP LOCKED for row-level locks](https://www.depesz.com/2014/10/10/waiting-for-9-5-implement-skip-locked-for-row-level-locks/) -### 13.16 Distributed processes +### 12.16 Distributed processes - 📝 [Héctor García-Molina, Kenneth Salem - Sagas](https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf) - 🎞 [Caitie McCaffrey - Applying the Saga Pattern](https://www.youtube.com/watch?v=xDuwrtwYHu8) - 🎞 [Chris Condron - Process Managers Made Simple](https://www.youtube.com/watch?v=8dRwF_MbEMs) @@ -1041,7 +1025,7 @@ See more in: - 📝 [NServiceBus sagas: Integrations](https://docs.particular.net/tutorials/nservicebus-sagas/3-integration) - 📝 [Denis Rosa (Couchbase) - Saga Pattern | Application Transactions Using Microservices](https://blog.couchbase.com/saga-pattern-implement-business-transactions-using-microservices-part/) -### 13.17 Domain Driven Design +### 12.17 Domain Driven Design - 📖 [Eric Evans - DDD Reference](https://www.domainlanguage.com/ddd/reference/) - 📝 [Eric Evans - DDD and Microservices: At Last, Some Boundaries!](https://www.infoq.com/presentations/ddd-microservices-2016) - 📖 [Domain-Driven Design: The First 15 Years](https://leanpub.com/ddd_first_15_years/) @@ -1050,7 +1034,7 @@ See more in: - 📖 [DDD Quickly](https://www.infoq.com/minibooks/domain-driven-design-quickly) - 📝 [Vaughn Vernon - Reactive DDD: Modeling Uncertainty](https://www.infoq.com/presentations/reactive-ddd-distributed-systems) -### 13.18 Whitepapers +### 12.18 Whitepapers - 📖 [Pat Helland - Immutability Changes Everything](http://cidrdb.org/cidr2015/Papers/CIDR15_Paper16.pdf) - 📖 [C. Mohan, D. Haderle, B. Lindsay, H. Pirahesh and P. Schwarz - ARIES: A Transaction Recovery Method Supporting Fine-Granularity Locking and Partial Rollbacks Using Write-Ahead Logging](http://db.csail.mit.edu/madden/html/aries.pdf) - 📖 [P. O'Neil, E. Cheng, D. Gawlick, E. O'Neil - The Log-Structured Merge-Tree (LSM-Tree)](https://www.cs.umb.edu/~poneil/lsmtree.pdf) @@ -1058,7 +1042,7 @@ See more in: -### 13.19 This is NOT Event Sourcing (but Event Streaming) +### 12.19 This is NOT Event Sourcing (but Event Streaming) - 📝 [Confluent - Event sourcing, CQRS, stream processing and Apache Kafka: What's the connection?](https://www.confluent.io/blog/event-sourcing-cqrs-stream-processing-apache-kafka-whats-connection/) - 🎞 [InfoQ - Building Microservices with Event Sourcing and CQRS](https://www.infoq.com/presentations/microservices-event-sourcing-cqrs/) - 📝 [Chris Kiehl - Don't Let the Internet Dupe You, Event Sourcing is Hard](https://chriskiehl.com/article/event-sourcing-is-hard) @@ -1095,7 +1079,7 @@ See more in: - 📝 [Why Microservices Should use Event Sourcing](https://blog.bitsrc.io/why-microservices-should-use-event-sourcing-9755a54ebfb4) - 📝 [Event-driven architecture with microservices using event sourcing and CQRS](https://medium.com/@tprkvolkan/event-driven-architecture-with-microservices-using-event-sourcing-and-cqrs-1cc516c20143) -### 13.20 Event Sourcing Concerns +### 12.20 Event Sourcing Concerns - 📝 [Kacper Gunia - EventStoreDB vs Kafka](https://domaincentric.net/blog/eventstoredb-vs-kafka) - 📝 [Anton Stöckl - Event Sourcing: Why Kafka is not suitable as an Event Store](https://medium.com/@TonyBologni/event-sourcing-why-kafka-is-not-suitable-as-an-event-store-796e5d9ab63c) - 📝 [Vijay Nair - Axon and Kafka - How does Axon compare to Apache Kafka?](https://axoniq.io/blog-overview/axon-and-kafka-how-does-axon-compare-to-apache-kafka) @@ -1108,7 +1092,7 @@ See more in: - 📝 [Hugo Rocha - What they don’t tell you about event sourcing](https://medium.com/@hugo.oliveira.rocha/what-they-dont-tell-you-about-event-sourcing-6afc23c69e9a) - 📝 [Oskar uit de Bos - Stop overselling Event Sourcing as the silver bullet to microservice architectures](https://medium.com/swlh/stop-overselling-event-sourcing-as-the-silver-bullet-to-microservice-architectures-f43ca25ff9e7) -### 13.21 Architecture Weekly +### 12.21 Architecture Weekly If you're interested in Architecture resources, check my other repository: https://github.com/oskardudycz/ArchitectureWeekly/. It contains a weekly updated list of materials I found valuable and educational. diff --git a/Sample/AsyncProjections/SmartHome.Api/Controllers/MotionSensorsController.cs b/Sample/AsyncProjections/SmartHome.Api/Controllers/MotionSensorsController.cs index 0817107a5..6eb7661bf 100644 --- a/Sample/AsyncProjections/SmartHome.Api/Controllers/MotionSensorsController.cs +++ b/Sample/AsyncProjections/SmartHome.Api/Controllers/MotionSensorsController.cs @@ -29,7 +29,7 @@ public class MotionSensorsController: Controller [HttpGet] public Task> Get() { - return queryBus.Send>(GetMotionSensors.Create()); + return queryBus.Query>(GetMotionSensors.Create()); } [HttpPost] diff --git a/Sample/AsyncProjections/SmartHome.Api/Controllers/TemperatureMeasurementsController.cs b/Sample/AsyncProjections/SmartHome.Api/Controllers/TemperatureMeasurementsController.cs index 84bbeec01..bcd1997b5 100644 --- a/Sample/AsyncProjections/SmartHome.Api/Controllers/TemperatureMeasurementsController.cs +++ b/Sample/AsyncProjections/SmartHome.Api/Controllers/TemperatureMeasurementsController.cs @@ -28,7 +28,7 @@ public class TemperatureMeasurementsController: Controller [HttpGet] public Task> Get() => - queryBus.Send>( + queryBus.Query>( new GetTemperatureMeasurements() ); diff --git a/Sample/AsyncProjections/SmartHome.Temperature/MotionSensors/GettingMotionSensor/GetMotionSensor.cs b/Sample/AsyncProjections/SmartHome.Temperature/MotionSensors/GettingMotionSensor/GetMotionSensor.cs index aa2f70696..f1f147111 100644 --- a/Sample/AsyncProjections/SmartHome.Temperature/MotionSensors/GettingMotionSensor/GetMotionSensor.cs +++ b/Sample/AsyncProjections/SmartHome.Temperature/MotionSensors/GettingMotionSensor/GetMotionSensor.cs @@ -3,14 +3,11 @@ namespace SmartHome.Temperature.MotionSensors.GettingMotionSensor; -public class GetMotionSensors : IQuery> +public class GetMotionSensors { private GetMotionSensors(){ } - public static GetMotionSensors Create() - { - return new(); - } + public static GetMotionSensors Create() => new(); } public class HandleGetMotionSensors : IQueryHandler> @@ -26,4 +23,4 @@ public Task> Handle(GetMotionSensors request, Cancel { return querySession.Query().ToListAsync(cancellationToken); } -} \ No newline at end of file +} diff --git a/Sample/AsyncProjections/SmartHome.Temperature/TemperatureMeasurements/GettingTemperatureMeasurements/GetTemperatureMeasurements.cs b/Sample/AsyncProjections/SmartHome.Temperature/TemperatureMeasurements/GettingTemperatureMeasurements/GetTemperatureMeasurements.cs index fa575cce7..2c70f3c89 100644 --- a/Sample/AsyncProjections/SmartHome.Temperature/TemperatureMeasurements/GettingTemperatureMeasurements/GetTemperatureMeasurements.cs +++ b/Sample/AsyncProjections/SmartHome.Temperature/TemperatureMeasurements/GettingTemperatureMeasurements/GetTemperatureMeasurements.cs @@ -3,7 +3,7 @@ namespace SmartHome.Temperature.TemperatureMeasurements.GettingTemperatureMeasurements; -public record GetTemperatureMeasurements: IQuery>; +public record GetTemperatureMeasurements; public class HandleGetTemperatureMeasurements: IQueryHandler> { diff --git a/Sample/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs b/Sample/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs index b7aef1999..79d4026ff 100644 --- a/Sample/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs +++ b/Sample/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs @@ -120,7 +120,7 @@ public async Task CancelCart(Guid id) [HttpGet("{id}")] public async Task Get(Guid id) { - var result = await queryBus.Send(GetCartById.Create(id)); + var result = await queryBus.Query(GetCartById.Create(id)); Response.TrySetETagResponseHeader(result.Version); @@ -130,7 +130,7 @@ public async Task Get(Guid id) [HttpGet] public async Task> Get([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20) { - var pagedList = await queryBus.Send>(GetCarts.Create(pageNumber, pageSize)); + var pagedList = await queryBus.Query>(GetCarts.Create(pageNumber, pageSize)); return pagedList.ToResponse(); } @@ -139,7 +139,7 @@ public async Task> Get([FromQuery] int [HttpGet("{id}/history")] public async Task> GetHistory(Guid id) { - var pagedList = await queryBus.Send>(GetCartHistory.Create(id)); + var pagedList = await queryBus.Query>(GetCartHistory.Create(id)); return pagedList.ToResponse(); } @@ -147,6 +147,6 @@ public async Task> GetHistory(Guid id) [HttpGet("{id}/versions")] public Task GetVersion(Guid id, [FromQuery] GetCartAtVersionRequest? query) { - return queryBus.Send(GetCartAtVersion.Create(id, query?.Version)); + return queryBus.Query(GetCartAtVersion.Create(id, query?.Version)); } } diff --git a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs index ea07d0dc0..ad6a9fcd2 100644 --- a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs +++ b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs @@ -8,7 +8,7 @@ namespace Carts.ShoppingCarts.GettingCartAtVersion; public record GetCartAtVersion( Guid CartId, long Version -) : IQuery +) { public static GetCartAtVersion Create(Guid? cartId, long? version) { diff --git a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs index 08ee3e839..e3c581bfa 100644 --- a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs +++ b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs @@ -5,7 +5,7 @@ namespace Carts.ShoppingCarts.GettingCartById; public record GetCartById( Guid CartId -): IQuery +) { public static GetCartById Create(Guid cartId) { diff --git a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs index 4376602e4..81125c9ef 100644 --- a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs +++ b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs @@ -8,7 +8,7 @@ public record GetCartHistory( Guid CartId, int PageNumber, int PageSize -): IQuery> +) { public static GetCartHistory Create(Guid cartId, int pageNumber = 1, int pageSize = 20) { diff --git a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs index 2cdf20abf..c3e547ed2 100644 --- a/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs +++ b/Sample/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs @@ -7,7 +7,7 @@ namespace Carts.ShoppingCarts.GettingCarts; public record GetCarts( int PageNumber, int PageSize -): IQuery> +) { public static GetCarts Create(int? pageNumber = 1, int? pageSize = 20) { diff --git a/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs b/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs index 7faa6d5cf..c720d6fa6 100644 --- a/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs +++ b/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Controllers/ShoppingCartsController.cs @@ -120,7 +120,7 @@ public async Task CancelCart(Guid id) [HttpGet("{id}")] public async Task Get(Guid id) { - var result = await queryBus.Send(GetCartById.Create(id)); + var result = await queryBus.Query(GetCartById.Create(id)); Response.TrySetETagResponseHeader(result.Version); @@ -131,7 +131,7 @@ public async Task Get(Guid id) public async Task> Get([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20) { - var pagedList = await queryBus.Send>(GetCarts.Create(pageNumber, pageSize)); + var pagedList = await queryBus.Query>(GetCarts.Create(pageNumber, pageSize)); return pagedList.ToResponse(); } @@ -140,7 +140,7 @@ public async Task Get(Guid id) [HttpGet("{id}/history")] public async Task> GetHistory(Guid id) { - var pagedList = await queryBus.Send>(GetCartHistory.Create(id)); + var pagedList = await queryBus.Query>(GetCartHistory.Create(id)); return pagedList.ToResponse(); } @@ -148,6 +148,6 @@ public async Task> GetHistory(Guid id) [HttpGet("{id}/versions")] public Task GetVersion(Guid id, [FromQuery] GetCartAtVersion? query) { - return queryBus.Send(GetCartAtVersion.Create(id, query?.Version)); + return queryBus.Query(GetCartAtVersion.Create(id, query?.Version)); } } diff --git a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs index aa18e3f94..7450fbc99 100644 --- a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs +++ b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartAtVersion/GetCartAtVersion.cs @@ -9,7 +9,7 @@ namespace Carts.ShoppingCarts.GettingCartAtVersion; public record GetCartAtVersion( Guid CartId, ulong Version -): IQuery +) { public static GetCartAtVersion Create(Guid? cartId, ulong? version) { diff --git a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs index 129445ba4..0dc431503 100644 --- a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs +++ b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartById/GetCartById.cs @@ -6,7 +6,7 @@ namespace Carts.ShoppingCarts.GettingCartById; public record GetCartById( Guid CartId - ) : IQuery +) { public static GetCartById Create(Guid? cartId) { diff --git a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs index 90978a921..4fa0b9d4f 100644 --- a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs +++ b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCartHistory/GetCartHistory.cs @@ -8,7 +8,7 @@ public record GetCartHistory( Guid CartId, int PageNumber, int PageSize -): IQuery> +) { public static GetCartHistory Create(Guid? cartId, int? pageNumber = 1, int? pageSize = 20) { diff --git a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs index 54210e8d4..fa05127a2 100644 --- a/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs +++ b/Sample/EventStoreDB/ECommerce/Carts/Carts/ShoppingCarts/GettingCarts/GetCarts.cs @@ -7,7 +7,7 @@ namespace Carts.ShoppingCarts.GettingCarts; public record GetCarts( int PageNumber, int PageSize -): IQuery> +) { public static GetCarts Create(int? pageNumber = 1, int? pageSize = 20) { diff --git a/Sample/MeetingsManagement/MeetingsManagement.Api/Controllers/MeetingsController.cs b/Sample/MeetingsManagement/MeetingsManagement.Api/Controllers/MeetingsController.cs index aaf2e047d..092031e15 100644 --- a/Sample/MeetingsManagement/MeetingsManagement.Api/Controllers/MeetingsController.cs +++ b/Sample/MeetingsManagement/MeetingsManagement.Api/Controllers/MeetingsController.cs @@ -25,7 +25,7 @@ public MeetingsController(ICommandBus commandBus, IQueryBus queryBus) public async Task Get(Guid id) { - var result = await queryBus.Send(new GetMeeting(id)); + var result = await queryBus.Query(new GetMeeting(id)); Response.TrySetETagResponseHeader(result.Version); diff --git a/Sample/MeetingsManagement/MeetingsManagement/Meetings/GettingMeeting/GetMeeting.cs b/Sample/MeetingsManagement/MeetingsManagement/Meetings/GettingMeeting/GetMeeting.cs index de0d0dbc9..b9450b633 100644 --- a/Sample/MeetingsManagement/MeetingsManagement/Meetings/GettingMeeting/GetMeeting.cs +++ b/Sample/MeetingsManagement/MeetingsManagement/Meetings/GettingMeeting/GetMeeting.cs @@ -5,7 +5,7 @@ namespace MeetingsManagement.Meetings.GettingMeeting; public record GetMeeting( Guid Id -): IQuery; +); internal class HandleGetMeeting: IQueryHandler @@ -23,4 +23,4 @@ IDocumentSession session { return session.LoadAsync(request.Id, cancellationToken); } -} \ No newline at end of file +} diff --git a/Sample/MeetingsManagement/MeetingsSearch.Api/Controllers/MeetingsController.cs b/Sample/MeetingsManagement/MeetingsSearch.Api/Controllers/MeetingsController.cs index bf7bccb74..96ae86eee 100644 --- a/Sample/MeetingsManagement/MeetingsSearch.Api/Controllers/MeetingsController.cs +++ b/Sample/MeetingsManagement/MeetingsSearch.Api/Controllers/MeetingsController.cs @@ -18,6 +18,6 @@ public MeetingsController(IQueryBus queryBus) [HttpGet] public Task> Search([FromQuery]string filter) { - return queryBus.Send>(new SearchMeetings(filter)); + return queryBus.Query>(new SearchMeetings(filter)); } } \ No newline at end of file diff --git a/Sample/MeetingsManagement/MeetingsSearch/Meetings/SearchingMeetings/SearchMeetings.cs b/Sample/MeetingsManagement/MeetingsSearch/Meetings/SearchingMeetings/SearchMeetings.cs index 99d69bbcf..47db35aa9 100644 --- a/Sample/MeetingsManagement/MeetingsSearch/Meetings/SearchingMeetings/SearchMeetings.cs +++ b/Sample/MeetingsManagement/MeetingsSearch/Meetings/SearchingMeetings/SearchMeetings.cs @@ -3,7 +3,7 @@ namespace MeetingsSearch.Meetings.SearchingMeetings; -public class SearchMeetings: IQuery> +public class SearchMeetings { public string Filter { get; } @@ -34,4 +34,4 @@ public async Task> Handle(SearchMeetings query, Can return response.Documents; } -} \ No newline at end of file +} diff --git a/Sample/Tickets/Tickets.Api/Controllers/ReservationsController.cs b/Sample/Tickets/Tickets.Api/Controllers/ReservationsController.cs index 2af3d7a54..695ab878a 100644 --- a/Sample/Tickets/Tickets.Api/Controllers/ReservationsController.cs +++ b/Sample/Tickets/Tickets.Api/Controllers/ReservationsController.cs @@ -37,13 +37,13 @@ public class ReservationsController: Controller [HttpGet("{id}")] public Task Get(Guid id) { - return queryBus.Send(new GetReservationById(id)); + return queryBus.Query(new GetReservationById(id)); } [HttpGet] public async Task> Get([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20) { - var pagedList = await queryBus.Send>(GetReservations.Create(pageNumber, pageSize)); + var pagedList = await queryBus.Query>(GetReservations.Create(pageNumber, pageSize)); return PagedListResponse.From(pagedList); } @@ -52,7 +52,7 @@ public async Task> Get([FromQuery] int p [HttpGet("{id}/history")] public async Task> GetHistory(Guid id) { - var pagedList = await queryBus.Send>(GetReservationHistory.Create(id)); + var pagedList = await queryBus.Query>(GetReservationHistory.Create(id)); return PagedListResponse.From(pagedList); } @@ -63,7 +63,7 @@ public Task GetVersion(Guid id, [FromQuery] GetReservationDe if (request == null) throw new ArgumentNullException(nameof(request)); - return queryBus.Send(GetReservationAtVersion.Create(id, request.Version)); + return queryBus.Query(GetReservationAtVersion.Create(id, request.Version)); } [HttpPost] diff --git a/Sample/Tickets/Tickets/Reservations/CreatingTentativeReservation/CreateTentativeReservation.cs b/Sample/Tickets/Tickets/Reservations/CreatingTentativeReservation/CreateTentativeReservation.cs index f61233a0e..3c48c9d49 100644 --- a/Sample/Tickets/Tickets/Reservations/CreatingTentativeReservation/CreateTentativeReservation.cs +++ b/Sample/Tickets/Tickets/Reservations/CreatingTentativeReservation/CreateTentativeReservation.cs @@ -9,7 +9,7 @@ namespace Tickets.Reservations.CreatingTentativeReservation; public record CreateTentativeReservation( Guid ReservationId, Guid SeatId - ) : ICommand + ) { public static CreateTentativeReservation Create(Guid? reservationId, Guid? seatId) { diff --git a/Sample/Tickets/Tickets/Reservations/GettingReservationAtVersion/GetReservationAtVersion.cs b/Sample/Tickets/Tickets/Reservations/GettingReservationAtVersion/GetReservationAtVersion.cs index b9420a815..0efb943f2 100644 --- a/Sample/Tickets/Tickets/Reservations/GettingReservationAtVersion/GetReservationAtVersion.cs +++ b/Sample/Tickets/Tickets/Reservations/GettingReservationAtVersion/GetReservationAtVersion.cs @@ -8,7 +8,7 @@ namespace Tickets.Reservations.GettingReservationAtVersion; public record GetReservationAtVersion( Guid ReservationId, int Version -): IQuery +) { public static GetReservationAtVersion Create(Guid reservationId, int version) { diff --git a/Sample/Tickets/Tickets/Reservations/GettingReservationById/GetReservationById.cs b/Sample/Tickets/Tickets/Reservations/GettingReservationById/GetReservationById.cs index c220fa04f..73811d88b 100644 --- a/Sample/Tickets/Tickets/Reservations/GettingReservationById/GetReservationById.cs +++ b/Sample/Tickets/Tickets/Reservations/GettingReservationById/GetReservationById.cs @@ -6,7 +6,7 @@ namespace Tickets.Reservations.GettingReservationById; public record GetReservationById( Guid ReservationId -): IQuery; +); internal class HandleGetReservationById : @@ -24,4 +24,4 @@ public async Task Handle(GetReservationById request, Cancell return await querySession.LoadAsync(request.ReservationId, cancellationToken) ?? throw AggregateNotFoundException.For(request.ReservationId); } -} \ No newline at end of file +} diff --git a/Sample/Tickets/Tickets/Reservations/GettingReservationHistory/GetReservationHistory.cs b/Sample/Tickets/Tickets/Reservations/GettingReservationHistory/GetReservationHistory.cs index 0457b44ad..86a9992fa 100644 --- a/Sample/Tickets/Tickets/Reservations/GettingReservationHistory/GetReservationHistory.cs +++ b/Sample/Tickets/Tickets/Reservations/GettingReservationHistory/GetReservationHistory.cs @@ -8,7 +8,7 @@ public record GetReservationHistory( Guid ReservationId, int PageNumber, int PageSize -): IQuery> +) { public static GetReservationHistory Create(Guid reservationId, int pageNumber = 1, int pageSize = 20) { diff --git a/Sample/Tickets/Tickets/Reservations/GettingReservations/GetReservations.cs b/Sample/Tickets/Tickets/Reservations/GettingReservations/GetReservations.cs index ba16d49d9..86670cdaf 100644 --- a/Sample/Tickets/Tickets/Reservations/GettingReservations/GetReservations.cs +++ b/Sample/Tickets/Tickets/Reservations/GettingReservations/GetReservations.cs @@ -7,7 +7,7 @@ namespace Tickets.Reservations.GettingReservations; public record GetReservations( int PageNumber, int PageSize -): IQuery> +) { public static GetReservations Create(int pageNumber = 1, int pageSize = 20) {