Implemented unit tests for QueueArguments attribute
Added proof-of-concept test for TapetiClient using Testcontainers.NET Updated packages
This commit is contained in:
parent
7143ad3c2f
commit
178f0a4956
@ -7,10 +7,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="6.2.0" />
|
<PackageReference Include="Autofac" Version="6.5.0" />
|
||||||
<PackageReference Include="Castle.Windsor" Version="5.1.1" />
|
<PackageReference Include="Castle.Windsor" Version="5.1.2" />
|
||||||
<PackageReference Include="Ninject" Version="3.3.4" />
|
<PackageReference Include="Ninject" Version="3.3.6" />
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
<PackageReference Include="Unity" Version="5.11.10" />
|
<PackageReference Include="Unity" Version="5.11.10" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="6.2.0" />
|
<PackageReference Include="Autofac" Version="6.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -30,6 +30,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Castle.Windsor" Version="5.1.1" />
|
<PackageReference Include="Castle.Windsor" Version="5.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -30,6 +30,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -34,6 +34,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
|
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -48,6 +48,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
<PackageReference Include="Tapeti.Annotations" Version="3.0.0" />
|
<PackageReference Include="Tapeti.Annotations" Version="3.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ninject" Version="3.3.4" />
|
<PackageReference Include="Ninject" Version="3.3.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -30,6 +30,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -34,6 +34,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SimpleInjector" Version="5.3.0" />
|
<PackageReference Include="SimpleInjector" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -34,6 +34,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
79
Tapeti.Tests/Client/RabbitMQFixture.cs
Normal file
79
Tapeti.Tests/Client/RabbitMQFixture.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Docker.DotNet;
|
||||||
|
using Docker.DotNet.Models;
|
||||||
|
using DotNet.Testcontainers.Builders;
|
||||||
|
using DotNet.Testcontainers.Configurations;
|
||||||
|
using DotNet.Testcontainers.Containers;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Tapeti.Tests.Client
|
||||||
|
{
|
||||||
|
[CollectionDefinition(Name)]
|
||||||
|
public sealed class RabbitMQCollection : ICollectionFixture<RabbitMQFixture>
|
||||||
|
{
|
||||||
|
public const string Name = "RabbitMQ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public sealed class RabbitMQFixture : IAsyncLifetime
|
||||||
|
{
|
||||||
|
public static string RabbitMQUsername => "tapetitests";
|
||||||
|
public static string RabbitMQPassword => "topsecret1234";
|
||||||
|
|
||||||
|
public ushort RabbitMQPort { get; private set; }
|
||||||
|
public ushort RabbitMQManagementPort { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
private TestcontainerMessageBroker testcontainers;
|
||||||
|
|
||||||
|
private const int DefaultRabbitMQPort = 5672;
|
||||||
|
private const int DefaultRabbitMQManagementPort = 15672;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private const string ImageName = "rabbitmq";
|
||||||
|
private const string ImageTag = "3.11.3-alpine";
|
||||||
|
|
||||||
|
|
||||||
|
public async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
// Testcontainers does not seem to pull the image the first time.
|
||||||
|
// I didn't get it to work, even using WithImagePullPolicy from the latest beta.
|
||||||
|
// Note: running it the first time can take a while.
|
||||||
|
var client = new DockerClientConfiguration().CreateClient();
|
||||||
|
await client.Images.CreateImageAsync(
|
||||||
|
new ImagesCreateParameters
|
||||||
|
{
|
||||||
|
FromImage = ImageName,
|
||||||
|
Tag = ImageTag
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
new Progress<JSONMessage>());
|
||||||
|
|
||||||
|
// If you get a "Sequence contains no elements" error here: make sure Docker Desktop is running
|
||||||
|
var testcontainersBuilder = new TestcontainersBuilder<RabbitMqTestcontainer>()
|
||||||
|
.WithMessageBroker(new RabbitMqTestcontainerConfiguration($"{ImageName}:{ImageTag}")
|
||||||
|
{
|
||||||
|
Username = RabbitMQUsername,
|
||||||
|
Password = RabbitMQPassword
|
||||||
|
})
|
||||||
|
.WithExposedPort(DefaultRabbitMQManagementPort)
|
||||||
|
.WithPortBinding(0, DefaultRabbitMQManagementPort);
|
||||||
|
|
||||||
|
testcontainers = testcontainersBuilder.Build();
|
||||||
|
|
||||||
|
await testcontainers.StartAsync();
|
||||||
|
|
||||||
|
RabbitMQPort = testcontainers.GetMappedPublicPort(DefaultRabbitMQPort);
|
||||||
|
RabbitMQManagementPort = testcontainers.GetMappedPublicPort(DefaultRabbitMQManagementPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task DisposeAsync()
|
||||||
|
{
|
||||||
|
if (testcontainers != null)
|
||||||
|
await testcontainers.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
Tapeti.Tests/Client/TapetiClientTests.cs
Normal file
75
Tapeti.Tests/Client/TapetiClientTests.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Tapeti.Connection;
|
||||||
|
using Tapeti.Tests.Mock;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace Tapeti.Tests.Client
|
||||||
|
{
|
||||||
|
[Collection(RabbitMQCollection.Name)]
|
||||||
|
public class TapetiClientTests
|
||||||
|
{
|
||||||
|
private readonly RabbitMQFixture fixture;
|
||||||
|
private readonly MockDependencyResolver dependencyResolver = new();
|
||||||
|
|
||||||
|
public TapetiClientTests(RabbitMQFixture fixture, ITestOutputHelper testOutputHelper)
|
||||||
|
{
|
||||||
|
this.fixture = fixture;
|
||||||
|
|
||||||
|
dependencyResolver.Set<ILogger>(new MockLogger(testOutputHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Fixture()
|
||||||
|
{
|
||||||
|
fixture.RabbitMQPort.Should().BeGreaterThan(0);
|
||||||
|
fixture.RabbitMQManagementPort.Should().BeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DynamicQueueDeclareNoPrefix()
|
||||||
|
{
|
||||||
|
var client = CreateCilent();
|
||||||
|
|
||||||
|
var queueName = await client.DynamicQueueDeclare(null, null, CancellationToken.None);
|
||||||
|
queueName.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
|
await client.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DynamicQueueDeclarePrefix()
|
||||||
|
{
|
||||||
|
var client = CreateCilent();
|
||||||
|
|
||||||
|
var queueName = await client.DynamicQueueDeclare("dynamicprefix", null, CancellationToken.None);
|
||||||
|
queueName.Should().StartWith("dynamicprefix");
|
||||||
|
|
||||||
|
await client.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO test the other methods
|
||||||
|
|
||||||
|
|
||||||
|
private TapetiClient CreateCilent()
|
||||||
|
{
|
||||||
|
return new TapetiClient(
|
||||||
|
new TapetiConfig.Config(dependencyResolver),
|
||||||
|
new TapetiConnectionParams
|
||||||
|
{
|
||||||
|
HostName = "127.0.0.1",
|
||||||
|
Port = fixture.RabbitMQPort,
|
||||||
|
ManagementPort = fixture.RabbitMQManagementPort,
|
||||||
|
Username = RabbitMQFixture.RabbitMQUsername,
|
||||||
|
Password = RabbitMQFixture.RabbitMQPassword,
|
||||||
|
PrefetchCount = 50
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
Tapeti.Tests/Config/BaseControllerTest.cs
Normal file
29
Tapeti.Tests/Config/BaseControllerTest.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using JetBrains.Annotations;
|
||||||
|
using Tapeti.Config;
|
||||||
|
using Tapeti.Tests.Mock;
|
||||||
|
|
||||||
|
namespace Tapeti.Tests.Config
|
||||||
|
{
|
||||||
|
public class BaseControllerTest
|
||||||
|
{
|
||||||
|
protected readonly MockDependencyResolver DependencyResolver = new();
|
||||||
|
|
||||||
|
|
||||||
|
protected ITapetiConfig GetControllerConfig<[MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] T>() where T : class
|
||||||
|
{
|
||||||
|
var configBuilder = new TapetiConfig(DependencyResolver);
|
||||||
|
|
||||||
|
configBuilder.EnableDeclareDurableQueues();
|
||||||
|
configBuilder.RegisterController(typeof(T));
|
||||||
|
var config = configBuilder.Build();
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected ITapetiConfigBindings GetControllerBindings<[MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] T>() where T : class
|
||||||
|
{
|
||||||
|
return GetControllerConfig<T>().Bindings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
199
Tapeti.Tests/Config/QueueArgumentsTest.cs
Normal file
199
Tapeti.Tests/Config/QueueArgumentsTest.cs
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using FluentAssertions.Execution;
|
||||||
|
using Moq;
|
||||||
|
using Tapeti.Annotations;
|
||||||
|
using Tapeti.Config;
|
||||||
|
using Tapeti.Connection;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Tapeti.Tests.Config
|
||||||
|
{
|
||||||
|
public class QueueArgumentsTest : BaseControllerTest
|
||||||
|
{
|
||||||
|
private static readonly MockRepository MoqRepository = new(MockBehavior.Strict);
|
||||||
|
|
||||||
|
private readonly Mock<ITapetiClient> client;
|
||||||
|
private readonly Dictionary<string, IReadOnlyDictionary<string, string>> declaredQueues = new();
|
||||||
|
|
||||||
|
|
||||||
|
public QueueArgumentsTest()
|
||||||
|
{
|
||||||
|
client = MoqRepository.Create<ITapetiClient>();
|
||||||
|
var routingKeyStrategy = MoqRepository.Create<IRoutingKeyStrategy>();
|
||||||
|
var exchangeStrategy = MoqRepository.Create<IExchangeStrategy>();
|
||||||
|
|
||||||
|
DependencyResolver.Set(routingKeyStrategy.Object);
|
||||||
|
DependencyResolver.Set(exchangeStrategy.Object);
|
||||||
|
|
||||||
|
|
||||||
|
routingKeyStrategy
|
||||||
|
.Setup(s => s.GetRoutingKey(typeof(TestMessage1)))
|
||||||
|
.Returns("testmessage1");
|
||||||
|
|
||||||
|
routingKeyStrategy
|
||||||
|
.Setup(s => s.GetRoutingKey(typeof(TestMessage2)))
|
||||||
|
.Returns("testmessage2");
|
||||||
|
|
||||||
|
exchangeStrategy
|
||||||
|
.Setup(s => s.GetExchange(It.IsAny<Type>()))
|
||||||
|
.Returns("exchange");
|
||||||
|
|
||||||
|
var queue = 0;
|
||||||
|
client
|
||||||
|
.Setup(c => c.DynamicQueueDeclare(null, It.IsAny<IReadOnlyDictionary<string, string>>(), It.IsAny<CancellationToken>()))
|
||||||
|
.Callback((string _, IReadOnlyDictionary<string, string> arguments, CancellationToken _) =>
|
||||||
|
{
|
||||||
|
queue++;
|
||||||
|
declaredQueues.Add($"queue-{queue}", arguments);
|
||||||
|
})
|
||||||
|
.ReturnsAsync(() => $"queue-{queue}");
|
||||||
|
|
||||||
|
client
|
||||||
|
.Setup(c => c.DurableQueueDeclare(It.IsAny<string>(), It.IsAny<IEnumerable<QueueBinding>>(), It.IsAny<IReadOnlyDictionary<string, string>>(), It.IsAny<CancellationToken>()))
|
||||||
|
.Callback((string queueName, IEnumerable<QueueBinding> _, IReadOnlyDictionary<string, string> arguments, CancellationToken _) =>
|
||||||
|
{
|
||||||
|
declaredQueues.Add(queueName, arguments);
|
||||||
|
})
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
|
||||||
|
client
|
||||||
|
.Setup(c => c.DynamicQueueBind(It.IsAny<string>(), It.IsAny<QueueBinding>(), It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SingleQueueArguments()
|
||||||
|
{
|
||||||
|
var config = GetControllerConfig<TestController>();
|
||||||
|
|
||||||
|
var binding1 = config.Bindings.Single(b => b is IControllerMethodBinding cmb && cmb.Method.Name == "HandleMessage1");
|
||||||
|
binding1.Should().NotBeNull();
|
||||||
|
|
||||||
|
var binding2 = config.Bindings.Single(b => b is IControllerMethodBinding cmb && cmb.Method.Name == "HandleMessage2");
|
||||||
|
binding2.Should().NotBeNull();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var subscriber = new TapetiSubscriber(() => client.Object, config);
|
||||||
|
await subscriber.ApplyBindings();
|
||||||
|
|
||||||
|
|
||||||
|
declaredQueues.Should().HaveCount(1);
|
||||||
|
var arguments = declaredQueues["queue-1"];
|
||||||
|
|
||||||
|
arguments.Should().ContainKey("x-custom").WhoseValue.Should().Be("custom value");
|
||||||
|
arguments.Should().ContainKey("x-another").WhoseValue.Should().Be("another value");
|
||||||
|
arguments.Should().ContainKey("x-max-length").WhoseValue.Should().Be("100");
|
||||||
|
arguments.Should().ContainKey("x-max-length-bytes").WhoseValue.Should().Be("100000");
|
||||||
|
arguments.Should().ContainKey("x-message-ttl").WhoseValue.Should().Be("4269");
|
||||||
|
arguments.Should().ContainKey("x-overflow").WhoseValue.Should().Be("reject-publish");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConflictingDynamicQueueArguments()
|
||||||
|
{
|
||||||
|
var config = GetControllerConfig<ConflictingArgumentsTestController>();
|
||||||
|
|
||||||
|
var subscriber = new TapetiSubscriber(() => client.Object, config);
|
||||||
|
await subscriber.ApplyBindings();
|
||||||
|
|
||||||
|
declaredQueues.Should().HaveCount(2);
|
||||||
|
|
||||||
|
var arguments1 = declaredQueues["queue-1"];
|
||||||
|
arguments1.Should().ContainKey("x-max-length").WhoseValue.Should().Be("100");
|
||||||
|
|
||||||
|
var arguments2 = declaredQueues["queue-2"];
|
||||||
|
arguments2.Should().ContainKey("x-max-length-bytes").WhoseValue.Should().Be("100000");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ConflictingDurableQueueArguments()
|
||||||
|
{
|
||||||
|
var config = GetControllerConfig<ConflictingArgumentsDurableQueueTestController>();
|
||||||
|
|
||||||
|
var testApplyBindings = () =>
|
||||||
|
{
|
||||||
|
var subscriber = new TapetiSubscriber(() => client.Object, config);
|
||||||
|
return subscriber.ApplyBindings();
|
||||||
|
};
|
||||||
|
|
||||||
|
using (new AssertionScope())
|
||||||
|
{
|
||||||
|
await testApplyBindings.Should().ThrowAsync<TopologyConfigurationException>();
|
||||||
|
declaredQueues.Should().HaveCount(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable all
|
||||||
|
#pragma warning disable
|
||||||
|
|
||||||
|
private class TestMessage1
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class TestMessage2
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[DynamicQueue]
|
||||||
|
[QueueArguments("x-custom", "custom value", "x-another", "another value", MaxLength = 100, MaxLengthBytes = 100000, MessageTTL = 4269, Overflow = RabbitMQOverflow.RejectPublish)]
|
||||||
|
private class TestController
|
||||||
|
{
|
||||||
|
public void HandleMessage1(TestMessage1 message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void HandleMessage2(TestMessage2 message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[DynamicQueue]
|
||||||
|
[QueueArguments(MaxLength = 100)]
|
||||||
|
private class ConflictingArgumentsTestController
|
||||||
|
{
|
||||||
|
public void HandleMessage1(TestMessage1 message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[QueueArguments(MaxLengthBytes = 100000)]
|
||||||
|
public void HandleMessage2(TestMessage1 message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[DurableQueue("durable")]
|
||||||
|
[QueueArguments(MaxLength = 100)]
|
||||||
|
private class ConflictingArgumentsDurableQueueTestController
|
||||||
|
{
|
||||||
|
public void HandleMessage1(TestMessage1 message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[QueueArguments(MaxLengthBytes = 100000)]
|
||||||
|
public void HandleMessage2(TestMessage1 message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning restore
|
||||||
|
// ReSharper restore all
|
||||||
|
}
|
||||||
|
}
|
43
Tapeti.Tests/Config/SimpleControllerTest.cs
Normal file
43
Tapeti.Tests/Config/SimpleControllerTest.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Tapeti.Annotations;
|
||||||
|
using Tapeti.Config;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Tapeti.Tests.Config
|
||||||
|
{
|
||||||
|
public class SimpleControllerTest : BaseControllerTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void RegisterController()
|
||||||
|
{
|
||||||
|
var bindings = GetControllerBindings<TestController>();
|
||||||
|
bindings.Should().HaveCount(1);
|
||||||
|
|
||||||
|
var handleSimpleMessageBinding = bindings.Single(b => b is IControllerMethodBinding cmb &&
|
||||||
|
cmb.Controller == typeof(TestController) &&
|
||||||
|
cmb.Method.Name == "HandleSimpleMessage");
|
||||||
|
handleSimpleMessageBinding.QueueType.Should().Be(QueueType.Dynamic);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable all
|
||||||
|
#pragma warning disable
|
||||||
|
|
||||||
|
private class TestMessage
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[DynamicQueue]
|
||||||
|
private class TestController
|
||||||
|
{
|
||||||
|
public void HandleSimpleMessage(TestMessage message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning restore
|
||||||
|
// ReSharper restore all
|
||||||
|
}
|
||||||
|
}
|
28
Tapeti.Tests/Mock/MockDependencyResolver.cs
Normal file
28
Tapeti.Tests/Mock/MockDependencyResolver.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Tapeti.Tests.Mock
|
||||||
|
{
|
||||||
|
public class MockDependencyResolver : IDependencyResolver
|
||||||
|
{
|
||||||
|
private readonly Dictionary<Type, object> container = new();
|
||||||
|
|
||||||
|
|
||||||
|
public void Set<TInterface>(TInterface instance)
|
||||||
|
{
|
||||||
|
container.Add(typeof(TInterface), instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public T Resolve<T>() where T : class
|
||||||
|
{
|
||||||
|
return (T)Resolve(typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public object Resolve(Type type)
|
||||||
|
{
|
||||||
|
return container[type];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
Tapeti.Tests/Mock/MockLogger.cs
Normal file
88
Tapeti.Tests/Mock/MockLogger.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Tapeti.Config;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace Tapeti.Tests.Mock
|
||||||
|
{
|
||||||
|
internal class MockLogger : IBindingLogger
|
||||||
|
{
|
||||||
|
private readonly ITestOutputHelper testOutputHelper;
|
||||||
|
|
||||||
|
|
||||||
|
public MockLogger(ITestOutputHelper testOutputHelper)
|
||||||
|
{
|
||||||
|
this.testOutputHelper = testOutputHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Connect(IConnectContext connectContext)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine($"{(connectContext.IsReconnect ? "Reconnecting" : "Connecting")} to {connectContext.ConnectionParams.HostName}:{connectContext.ConnectionParams.Port}{connectContext.ConnectionParams.VirtualHost}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConnectFailed(IConnectFailedContext connectContext)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine($"Connection failed: {connectContext.Exception}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConnectSuccess(IConnectSuccessContext connectContext)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine($"{(connectContext.IsReconnect ? "Reconnected" : "Connected")} using local port {connectContext.LocalPort}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect(IDisconnectContext disconnectContext)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine($"Connection closed: {(!string.IsNullOrEmpty(disconnectContext.ReplyText) ? disconnectContext.ReplyText : "<no reply text>")} (reply code: {disconnectContext.ReplyCode})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConsumeException(Exception exception, IMessageContext messageContext, ConsumeResult consumeResult)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine(exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueDeclare(string queueName, bool durable, bool passive)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine(passive
|
||||||
|
? $"Verifying durable queue {queueName}"
|
||||||
|
: $"Declaring {(durable ? "durable" : "dynamic")} queue {queueName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueExistsWarning(string queueName, IReadOnlyDictionary<string, string> existingArguments, IReadOnlyDictionary<string, string> arguments)
|
||||||
|
{
|
||||||
|
var argumentsText = new StringBuilder();
|
||||||
|
foreach (var pair in arguments)
|
||||||
|
{
|
||||||
|
if (argumentsText.Length > 0)
|
||||||
|
argumentsText.Append(", ");
|
||||||
|
|
||||||
|
argumentsText.Append($"{pair.Key} = {pair.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputHelper.WriteLine($"Durable queue {queueName} exists with incompatible x-arguments ({argumentsText}) and will not be redeclared, queue will be consumed as-is");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueBind(string queueName, bool durable, string exchange, string routingKey)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine($"Binding {queueName} to exchange {exchange} with routing key {routingKey}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueUnbind(string queueName, string exchange, string routingKey)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine($"Removing binding for {queueName} to exchange {exchange} with routing key {routingKey}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExchangeDeclare(string exchange)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine($"Declaring exchange {exchange}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueObsolete(string queueName, bool deleted, uint messageCount)
|
||||||
|
{
|
||||||
|
testOutputHelper.WriteLine(deleted
|
||||||
|
? $"Obsolete queue was deleted: {queueName}"
|
||||||
|
: $"Obsolete queue bindings removed: {queueName}, {messageCount} messages remaining");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,10 +15,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
<PackageReference Include="FluentAssertions" Version="6.8.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
<PackageReference Include="Moq" Version="4.18.2" />
|
||||||
|
<PackageReference Include="Testcontainers" Version="2.2.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.4.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -30,6 +30,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -30,6 +30,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -118,7 +118,7 @@ namespace Tapeti.Config
|
|||||||
/// before the configuration is built. Implementations of ITapetiConfigBuilder should also implement this interface.
|
/// before the configuration is built. Implementations of ITapetiConfigBuilder should also implement this interface.
|
||||||
/// Should not be used outside of Tapeti packages.
|
/// Should not be used outside of Tapeti packages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITapetiConfigBuilderAccess
|
public interface ITapetiConfigBuilderAccess : ITapetiConfigBuilder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides access to the dependency resolver.
|
/// Provides access to the dependency resolver.
|
||||||
|
3
Tapeti/Properties/AssemblyInfo.cs
Normal file
3
Tapeti/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("Tapeti.Tests")]
|
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="6.2.1" />
|
<PackageReference Include="RabbitMQ.Client" Version="6.4.0" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
<PackageReference Include="Tapeti.Annotations" Version="3.*-*" />
|
<PackageReference Include="Tapeti.Annotations" Version="3.*-*" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -15,7 +15,7 @@ namespace Tapeti
|
|||||||
/// Default implementation of the Tapeti config builder.
|
/// Default implementation of the Tapeti config builder.
|
||||||
/// Automatically registers the default middleware for injecting the message parameter and handling the return value.
|
/// Automatically registers the default middleware for injecting the message parameter and handling the return value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TapetiConfig : ITapetiConfigBuilder, ITapetiConfigBuilderAccess
|
public class TapetiConfig : ITapetiConfigBuilderAccess
|
||||||
{
|
{
|
||||||
private Config config;
|
private Config config;
|
||||||
private readonly List<IControllerBindingMiddleware> bindingMiddleware = new();
|
private readonly List<IControllerBindingMiddleware> bindingMiddleware = new();
|
||||||
|
@ -38,7 +38,7 @@ namespace Tapeti
|
|||||||
if (!controller.IsClass)
|
if (!controller.IsClass)
|
||||||
throw new ArgumentException($"Controller {controller.Name} must be a class");
|
throw new ArgumentException($"Controller {controller.Name} must be a class");
|
||||||
|
|
||||||
var controllerQueueInfo = GetQueueInfo(controller);
|
var controllerQueueInfo = GetQueueInfo(controller, null);
|
||||||
(builderAccess.DependencyResolver as IDependencyContainer)?.RegisterController(controller);
|
(builderAccess.DependencyResolver as IDependencyContainer)?.RegisterController(controller);
|
||||||
|
|
||||||
var controllerIsObsolete = controller.GetCustomAttribute<ObsoleteAttribute>() != null;
|
var controllerIsObsolete = controller.GetCustomAttribute<ObsoleteAttribute>() != null;
|
||||||
@ -79,7 +79,7 @@ namespace Tapeti
|
|||||||
throw new TopologyConfigurationException($"Method {method.Name} in controller {method.DeclaringType?.Name} has unknown parameters: {parameterNames}");
|
throw new TopologyConfigurationException($"Method {method.Name} in controller {method.DeclaringType?.Name} has unknown parameters: {parameterNames}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var methodQueueInfo = GetQueueInfo(method) ?? controllerQueueInfo;
|
var methodQueueInfo = GetQueueInfo(method, controllerQueueInfo);
|
||||||
if (methodQueueInfo is not { IsValid: true })
|
if (methodQueueInfo is not { IsValid: true })
|
||||||
throw new TopologyConfigurationException(
|
throw new TopologyConfigurationException(
|
||||||
$"Method {method.Name} or controller {controller.Name} requires a queue attribute");
|
$"Method {method.Name} or controller {controller.Name} requires a queue attribute");
|
||||||
@ -129,23 +129,45 @@ namespace Tapeti
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static ControllerMethodBinding.QueueInfo GetQueueInfo(MemberInfo member)
|
private static ControllerMethodBinding.QueueInfo GetQueueInfo(MemberInfo member, ControllerMethodBinding.QueueInfo fallbackQueueInfo)
|
||||||
{
|
{
|
||||||
var dynamicQueueAttribute = member.GetCustomAttribute<DynamicQueueAttribute>();
|
var dynamicQueueAttribute = member.GetCustomAttribute<DynamicQueueAttribute>();
|
||||||
var durableQueueAttribute = member.GetCustomAttribute<DurableQueueAttribute>();
|
var durableQueueAttribute = member.GetCustomAttribute<DurableQueueAttribute>();
|
||||||
|
var queueArgumentsAttribute = member.GetCustomAttribute<QueueArgumentsAttribute>();
|
||||||
|
|
||||||
if (dynamicQueueAttribute != null && durableQueueAttribute != null)
|
if (dynamicQueueAttribute != null && durableQueueAttribute != null)
|
||||||
throw new TopologyConfigurationException($"Cannot combine static and dynamic queue attributes on controller {member.DeclaringType?.Name} method {member.Name}");
|
throw new TopologyConfigurationException($"Cannot combine static and dynamic queue attributes on controller {member.DeclaringType?.Name} method {member.Name}");
|
||||||
|
|
||||||
|
if (dynamicQueueAttribute == null && durableQueueAttribute == null && (queueArgumentsAttribute == null || fallbackQueueInfo == null))
|
||||||
|
return fallbackQueueInfo;
|
||||||
|
|
||||||
|
|
||||||
|
QueueType queueType;
|
||||||
|
string name;
|
||||||
|
|
||||||
var queueArgumentsAttribute = member.GetCustomAttribute<QueueArgumentsAttribute>();
|
|
||||||
|
|
||||||
if (dynamicQueueAttribute != null)
|
if (dynamicQueueAttribute != null)
|
||||||
return new ControllerMethodBinding.QueueInfo { QueueType = QueueType.Dynamic, Name = dynamicQueueAttribute.Prefix, QueueArguments = GetQueueArguments(queueArgumentsAttribute) };
|
{
|
||||||
|
queueType = QueueType.Dynamic;
|
||||||
|
name = dynamicQueueAttribute.Prefix;
|
||||||
|
}
|
||||||
|
else if (durableQueueAttribute != null)
|
||||||
|
{
|
||||||
|
queueType = QueueType.Durable;
|
||||||
|
name = durableQueueAttribute.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queueType = fallbackQueueInfo.QueueType;
|
||||||
|
name = fallbackQueueInfo.Name;
|
||||||
|
}
|
||||||
|
|
||||||
return durableQueueAttribute != null
|
return new ControllerMethodBinding.QueueInfo
|
||||||
? new ControllerMethodBinding.QueueInfo { QueueType = QueueType.Durable, Name = durableQueueAttribute.Name, QueueArguments = GetQueueArguments(queueArgumentsAttribute) }
|
{
|
||||||
: null;
|
QueueType = queueType,
|
||||||
|
Name = name,
|
||||||
|
QueueArguments = GetQueueArguments(queueArgumentsAttribute) ?? fallbackQueueInfo?.QueueArguments
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user