pipeline cache and dispatch optimizations
This commit is contained in:
@@ -6,6 +6,10 @@ namespace Cqrs.Tests.CommandDispatcherImplTests;
|
||||
|
||||
public class Dispatch
|
||||
{
|
||||
public abstract class TestCommandHandler : ICommandHandler<TestCommand, TestCommandResult>
|
||||
{
|
||||
public abstract ValueTask<TestCommandResult> Handle(TestCommand command, CancellationToken cancellation);
|
||||
}
|
||||
public class TestCommand : IKnownCommand<TestCommandResult> {}
|
||||
public class TestCommandResult {}
|
||||
|
||||
@@ -19,7 +23,7 @@ public class Dispatch
|
||||
var testCommand = new TestCommand();
|
||||
var testCommandResult = new TestCommandResult();
|
||||
|
||||
var commandHandler = Substitute.For<ICommandHandler<TestCommand, TestCommandResult>>();
|
||||
var commandHandler = Substitute.For<TestCommandHandler>();
|
||||
commandHandler.Handle(testCommand, CancellationToken.None).Returns(testCommandResult);
|
||||
|
||||
ServiceCollection serviceCollection =
|
||||
@@ -67,7 +71,7 @@ public class Dispatch
|
||||
var testCommandResult = new TestCommandResult();
|
||||
List<string> calls = [];
|
||||
|
||||
var commandHandler = Substitute.For<ICommandHandler<TestCommand, TestCommandResult>>();
|
||||
var commandHandler = Substitute.For<TestCommandHandler>();
|
||||
commandHandler.Handle(testCommand, CancellationToken.None)
|
||||
.Returns(testCommandResult)
|
||||
.AndDoes(_ => calls.Add("commandHandler"));
|
||||
@@ -131,7 +135,7 @@ public class Dispatch
|
||||
var testCommandResultAborted = new TestCommandResult();
|
||||
List<string> calls = [];
|
||||
|
||||
var commandHandler = Substitute.For<ICommandHandler<TestCommand, TestCommandResult>>();
|
||||
var commandHandler = Substitute.For<TestCommandHandler>();
|
||||
commandHandler.Handle(testCommand, CancellationToken.None)
|
||||
.Returns(testCommandResult)
|
||||
.AndDoes(_ => calls.Add("commandHandler"));
|
||||
@@ -185,4 +189,53 @@ public class Dispatch
|
||||
|
||||
calls.ShouldBe(["firstBehavior", "secondBehavior"]);
|
||||
}
|
||||
|
||||
public abstract class AnotherTestCommandHandler : ICommandHandler<TestCommand, AnotherTestCommandResult>
|
||||
{
|
||||
public abstract ValueTask<AnotherTestCommandResult> Handle(TestCommand command, CancellationToken cancellation);
|
||||
}
|
||||
public class AnotherTestCommandResult {}
|
||||
|
||||
[Fact]
|
||||
public async Task WhenTwoHandlersWithDifferentResultTypesRegisteredForOneCommandType_ShouldCorrectlyDispatchToBoth() // Fix to Cache Key Collision
|
||||
{
|
||||
// Given
|
||||
var testCommand = new TestCommand();
|
||||
var testCommandResult = new TestCommandResult();
|
||||
var anotherTestCommandResult = new AnotherTestCommandResult();
|
||||
|
||||
var commandHandler = Substitute.For<TestCommandHandler>();
|
||||
commandHandler.Handle(testCommand, CancellationToken.None).Returns(testCommandResult);
|
||||
|
||||
var anotherCommandHandler = Substitute.For<AnotherTestCommandHandler>();
|
||||
anotherCommandHandler.Handle(testCommand, CancellationToken.None).Returns(anotherTestCommandResult);
|
||||
|
||||
ServiceCollection serviceCollection =
|
||||
[
|
||||
new ServiceDescriptor(
|
||||
typeof(ICommandHandler<TestCommand, TestCommandResult>),
|
||||
(IServiceProvider _) => commandHandler,
|
||||
ServiceLifetime.Transient
|
||||
),
|
||||
new ServiceDescriptor(
|
||||
typeof(ICommandHandler<TestCommand, AnotherTestCommandResult>),
|
||||
(IServiceProvider _) => anotherCommandHandler,
|
||||
ServiceLifetime.Transient
|
||||
),
|
||||
];
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var sut = new CommandDispatcherImpl(services, new ConcurrentMethodsCache());
|
||||
|
||||
// When
|
||||
var result = await sut.Dispatch(testCommand, CancellationToken.None);
|
||||
var anotherResult = await sut.Dispatch<AnotherTestCommandResult>(testCommand, CancellationToken.None);
|
||||
|
||||
// Then
|
||||
result.ShouldBeSameAs(testCommandResult);
|
||||
await commandHandler.Received(1).Handle(testCommand, CancellationToken.None);
|
||||
|
||||
anotherResult.ShouldBeSameAs(anotherTestCommandResult);
|
||||
await anotherCommandHandler.Received(1).Handle(testCommand, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ namespace Cqrs.Tests.QueryDispatcherImplTests;
|
||||
|
||||
public class Dispatch
|
||||
{
|
||||
public abstract class TestQueryHandler : IQueryHandler<TestQuery, TestQueryResult>
|
||||
{
|
||||
public abstract ValueTask<TestQueryResult> Handle(TestQuery query, CancellationToken cancellation);
|
||||
}
|
||||
public class TestQuery : IKnownQuery<TestQueryResult> {}
|
||||
public class TestQueryResult {}
|
||||
|
||||
@@ -19,7 +23,7 @@ public class Dispatch
|
||||
var testQuery = new TestQuery();
|
||||
var testQueryResult = new TestQueryResult();
|
||||
|
||||
var queryHandler = Substitute.For<IQueryHandler<TestQuery, TestQueryResult>>();
|
||||
var queryHandler = Substitute.For<TestQueryHandler>();
|
||||
queryHandler.Handle(testQuery, CancellationToken.None).Returns(testQueryResult);
|
||||
|
||||
ServiceCollection serviceCollection =
|
||||
@@ -67,7 +71,7 @@ public class Dispatch
|
||||
var testQueryResult = new TestQueryResult();
|
||||
List<string> calls = [];
|
||||
|
||||
var queryHandler = Substitute.For<IQueryHandler<TestQuery, TestQueryResult>>();
|
||||
var queryHandler = Substitute.For<TestQueryHandler>();
|
||||
queryHandler.Handle(testQuery, CancellationToken.None)
|
||||
.Returns(testQueryResult)
|
||||
.AndDoes(_ => calls.Add("queryHandler"));
|
||||
@@ -131,7 +135,7 @@ public class Dispatch
|
||||
var testQueryResultAborted = new TestQueryResult();
|
||||
List<string> calls = [];
|
||||
|
||||
var queryHandler = Substitute.For<IQueryHandler<TestQuery, TestQueryResult>>();
|
||||
var queryHandler = Substitute.For<TestQueryHandler>();
|
||||
queryHandler.Handle(testQuery, CancellationToken.None)
|
||||
.Returns(testQueryResult)
|
||||
.AndDoes(_ => calls.Add("queryHandler"));
|
||||
@@ -185,4 +189,53 @@ public class Dispatch
|
||||
|
||||
calls.ShouldBe(["firstBehavior", "secondBehavior"]);
|
||||
}
|
||||
|
||||
public abstract class AnotherTestQueryHandler : IQueryHandler<TestQuery, AnotherTestQueryResult>
|
||||
{
|
||||
public abstract ValueTask<AnotherTestQueryResult> Handle(TestQuery query, CancellationToken cancellation);
|
||||
}
|
||||
public class AnotherTestQueryResult {}
|
||||
|
||||
[Fact]
|
||||
public async Task WhenTwoHandlersWithDifferentResultTypesRegisteredForOneQueryType_ShouldCorrectlyDispatchToBoth() // Fix to Cache Key Collision
|
||||
{
|
||||
// Given
|
||||
var testQuery = new TestQuery();
|
||||
var testQueryResult = new TestQueryResult();
|
||||
var anotherTestQueryResult = new AnotherTestQueryResult();
|
||||
|
||||
var queryHandler = Substitute.For<TestQueryHandler>();
|
||||
queryHandler.Handle(testQuery, CancellationToken.None).Returns(testQueryResult);
|
||||
|
||||
var anotherQueryHandler = Substitute.For<AnotherTestQueryHandler>();
|
||||
anotherQueryHandler.Handle(testQuery, CancellationToken.None).Returns(anotherTestQueryResult);
|
||||
|
||||
ServiceCollection serviceCollection =
|
||||
[
|
||||
new ServiceDescriptor(
|
||||
typeof(IQueryHandler<TestQuery, TestQueryResult>),
|
||||
(IServiceProvider _) => queryHandler,
|
||||
ServiceLifetime.Transient
|
||||
),
|
||||
new ServiceDescriptor(
|
||||
typeof(IQueryHandler<TestQuery, AnotherTestQueryResult>),
|
||||
(IServiceProvider _) => anotherQueryHandler,
|
||||
ServiceLifetime.Transient
|
||||
),
|
||||
];
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var sut = new QueryDispatcherImpl(services, new ConcurrentMethodsCache());
|
||||
|
||||
// When
|
||||
var result = await sut.Dispatch(testQuery, CancellationToken.None);
|
||||
var anotherResult = await sut.Dispatch<AnotherTestQueryResult>(testQuery, CancellationToken.None);
|
||||
|
||||
// Then
|
||||
result.ShouldBeSameAs(testQueryResult);
|
||||
await queryHandler.Received(1).Handle(testQuery, CancellationToken.None);
|
||||
|
||||
anotherResult.ShouldBeSameAs(anotherTestQueryResult);
|
||||
await anotherQueryHandler.Received(1).Handle(testQuery, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user