Skip to content

Commit

Permalink
DI extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
sanych-sun committed Oct 18, 2024
1 parent b695a96 commit 7d98af3
Show file tree
Hide file tree
Showing 21 changed files with 180 additions and 22 deletions.
3 changes: 2 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<Project>
<PropertyGroup>
<Version>0.4.0</Version>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net6.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<LangVersion>latest</LangVersion>
<Authors>Oleksandr Poliakov</Authors>
<PackageTags>RabbitMQ;Messaging</PackageTags>
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The library was created with idea of the minimal possible allocation. Here is pe
## Packages
Too much packages instead of a single... explained:
- [RabbitMQ.Next](https://www.nuget.org/packages/RabbitMQ.Next), [RabbitMQ.Next.Abstractions](https://www.nuget.org/packages/RabbitMQ.Next.Abstractions) – core library, contains most of the protocol-level implementations
- [RabbitMQ.Next.DependencyInjection](https://www.nuget.org/packages/RabbitMQ.Next.DependencyInjection) - helper library for convenient registration of IConnection in DI container.
- [RabbitMQ.Next.TopologyBuilder](https://www.nuget.org/packages/RabbitMQ.Next.TopologyBuilder), [RabbitMQ.Next.TopologyBuilder.Abstractions](https://www.nuget.org/packages/RabbitMQ.Next.TopologyBuilder.Abstractions) – library contains methods to manage exchanges, queues and bindings
- [RabbitMQ.Next.Consumer](https://www.nuget.org/packages/RabbitMQ.Next.Consumer), [RabbitMQ.Next.Consumer.Abstractions](https://www.nuget.org/packages/RabbitMQ.Next.Consumer.Abstractions) – library provides high-level message consumption API
- [RabbitMQ.Next.Publisher](https://www.nuget.org/packages/RabbitMQ.Next.Publisher), [RabbitMQ.Next.Publisher.Abstractions](https://www.nuget.org/packages/RabbitMQ.Next.Publisher.Abstractions) – provides high-level message publishing API
Expand All @@ -47,8 +48,8 @@ First of all have to open the connection to RabbitMQ server:
using RabbitMQ.Next;
...

var connection = await ConnectionBuilder.Default
.Endpoint("amqp://guest:password@localhost:5672/")
var connection = ConnectionBuilder.Default
.UseConnectionString("amqp://guest:password@localhost:5672/")
.Build();
```

Expand Down
14 changes: 14 additions & 0 deletions RabbitMQ.Next.sln
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Next.Examples.Demo
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Next.Examples.PublisherMiddleware", "docs\examples\RabbitMQ.Next.Examples.PublisherMiddleware\RabbitMQ.Next.Examples.PublisherMiddleware.csproj", "{23340CFA-F105-4F7F-B2C5-16693A8626F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Next.DependencyInjection", "src\RabbitMQ.Next.DependencyInjection\RabbitMQ.Next.DependencyInjection.csproj", "{B4DC5006-903A-4E4F-A819-47CE0DDC3CF7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Next.Examples.DependencyInjection", "docs\examples\RabbitMQ.Next.Examples.DependencyInjection\RabbitMQ.Next.Examples.DependencyInjection.csproj", "{5841CCA0-850A-483D-841C-940967D619AD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -148,6 +152,14 @@ Global
{23340CFA-F105-4F7F-B2C5-16693A8626F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23340CFA-F105-4F7F-B2C5-16693A8626F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23340CFA-F105-4F7F-B2C5-16693A8626F9}.Release|Any CPU.Build.0 = Release|Any CPU
{B4DC5006-903A-4E4F-A819-47CE0DDC3CF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4DC5006-903A-4E4F-A819-47CE0DDC3CF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4DC5006-903A-4E4F-A819-47CE0DDC3CF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4DC5006-903A-4E4F-A819-47CE0DDC3CF7}.Release|Any CPU.Build.0 = Release|Any CPU
{5841CCA0-850A-483D-841C-940967D619AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5841CCA0-850A-483D-841C-940967D619AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5841CCA0-850A-483D-841C-940967D619AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5841CCA0-850A-483D-841C-940967D619AD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{AB00A6F3-C3E0-4E61-B302-F9CF0288819E} = {C895EE24-13DF-45C3-AF1D-B6B6EE4A10A9}
Expand All @@ -174,5 +186,7 @@ Global
{B93A51A9-0A31-4419-B8E8-C304EF18CFAB} = {750B1D71-E43B-4714-8AA3-AB9B0EC7E931}
{C0440748-9787-4891-874A-054F5E64020B} = {750B1D71-E43B-4714-8AA3-AB9B0EC7E931}
{23340CFA-F105-4F7F-B2C5-16693A8626F9} = {750B1D71-E43B-4714-8AA3-AB9B0EC7E931}
{B4DC5006-903A-4E4F-A819-47CE0DDC3CF7} = {C895EE24-13DF-45C3-AF1D-B6B6EE4A10A9}
{5841CCA0-850A-483D-841C-940967D619AD} = {750B1D71-E43B-4714-8AA3-AB9B0EC7E931}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Console.WriteLine("Hello World! Will try to connect RabbitMQ server with RABBIT-CR-DEMO auth mechanism.");

await using var connection = ConnectionBuilder.Default
.Endpoint("amqp://localhost:5672/")
.UseConnectionString("amqp://localhost:5672/")
.WithRabbitCrDemoAuth("guest", "guest")
.Build();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using RabbitMQ.Next;
using RabbitMQ.Next.DependencyInjection;
using RabbitMQ.Next.Examples.DependencyInjection;
using RabbitMQ.Next.Serialization.PlainText;

var builder = Host.CreateDefaultBuilder(args);

builder.ConfigureServices(services =>
{
services.AddRabbitMQConnection(
builder => builder
.UseConnectionString("amqp://guest:guest@localhost:5672/")
.UsePlainTextSerializer());
services.AddHostedService<Worker>();
});

using IHost host = builder.Build();

host.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\RabbitMQ.Next.DependencyInjection\RabbitMQ.Next.DependencyInjection.csproj" />
<ProjectReference Include="..\..\..\src\RabbitMQ.Next.Publisher\RabbitMQ.Next.Publisher.csproj" />
<ProjectReference Include="..\..\..\src\RabbitMQ.Next.Serialization.PlainText\RabbitMQ.Next.Serialization.PlainText.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
</ItemGroup>

</Project>
28 changes: 28 additions & 0 deletions docs/examples/RabbitMQ.Next.Examples.DependencyInjection/Worker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using RabbitMQ.Next.Publisher;

namespace RabbitMQ.Next.Examples.DependencyInjection;

public class Worker : BackgroundService
{
private readonly IPublisher _publisher;
private readonly IHostLifetime _hostLifetime;

public Worker(IConnection connection, IHostLifetime hostLifetime)
{
this._hostLifetime = hostLifetime;
this._publisher = connection.Publisher("amq.fanout");
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await this._publisher.PublishAsync("Hello World!", cancellation: stoppingToken);
Console.WriteLine("Message was published.");
Console.WriteLine("Press [Enter] key to exit...");
Console.ReadLine();
await this._hostLifetime.StopAsync(stoppingToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal static class Program
private static async Task Main()
{
await using var connection = ConnectionBuilder.Default
.Endpoint("amqp://test2:test2@localhost:5672/")
.UseConnectionString("amqp://guest:guest@localhost:5672/")
.UseDynamicSerializer(serializer => serializer
.When(m => "application/json".Equals(m.ContentType, StringComparison.InvariantCultureIgnoreCase)).UseSystemJsonSerializer()
.When(m => "application/msgpack".Equals(m.ContentType, StringComparison.InvariantCultureIgnoreCase)).UseMessagePackSerializer()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Console.WriteLine("Hello World! This is publisher based on RabbitMQ.Next library.");

var connection = ConnectionBuilder.Default
.Endpoint("amqp://guest:guest@localhost:5672/")
.UseConnectionString("amqp://guest:guest@localhost:5672/")
.UsePlainTextSerializer()
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Console.WriteLine("Hello World! This is consumer based on RabbitMQ.Next library.");

var connection = ConnectionBuilder.Default
.Endpoint("amqp://guest:guest@localhost:5672/")
.UseConnectionString("amqp://guest:guest@localhost:5672/")
.UsePlainTextSerializer()
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Console.WriteLine("Hello World! This is publisher based on RabbitMQ.Next library.");

var connection = ConnectionBuilder.Default
.Endpoint("amqp://guest:guest@localhost:5672/")
.UseConnectionString("amqp://guest:guest@localhost:5672/")
.UsePlainTextSerializer()
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Console.WriteLine("Hello World! This is topology builder based on RabbitMQ.Next library.");

var connection = ConnectionBuilder.Default
.Endpoint("amqp://guest:guest@localhost:5672/")
.UseConnectionString("amqp://guest:guest@localhost:5672/")
.Build();

await connection.ConfigureAsync(async topology =>
Expand Down
6 changes: 3 additions & 3 deletions src/RabbitMQ.Next.Abstractions/ConnectionBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ public static IConnectionBuilder PlainAuth(this IConnectionBuilder builder, stri
return builder;
}

public static IConnectionBuilder Endpoint(this IConnectionBuilder builder, string endpoint)
public static IConnectionBuilder UseConnectionString(this IConnectionBuilder builder, string endpoint)
{
endpoint = WebUtility.UrlDecode(endpoint);
if (Uri.TryCreate(endpoint, UriKind.Absolute, out var uri))
{
return builder.Endpoint(uri);
return builder.UseConnectionString(uri);
}

throw new ArgumentException("Cannot parse endpoint as Uri.",nameof(endpoint));
}

public static IConnectionBuilder Endpoint(this IConnectionBuilder builder, Uri endpoint)
public static IConnectionBuilder UseConnectionString(this IConnectionBuilder builder, Uri endpoint)
{
var parsed = ParseAmqpUri(endpoint);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\RabbitMQ.Next\RabbitMQ.Next.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Condition="'$(TargetFramework)' == 'net6.0'" Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
<PackageReference Condition="'$(TargetFramework)' == 'net8.0'" Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace RabbitMQ.Next.DependencyInjection;

public static class ServiceCollectionExtensions
{
#if NET8_0_OR_GREATER
public static IServiceCollection AddRabbitMQConnection(
this IServiceCollection serviceCollection,
Action<IConnectionBuilder> connectionBuilder,
ServiceLifetime lifetime = ServiceLifetime.Singleton,
object serviceKey = null)
{
serviceCollection.TryAdd(
new ServiceDescriptor(
typeof(IConnection),
serviceKey,
(sp, _) =>
{
var builder = ConnectionBuilder.Default;
connectionBuilder(builder);
return builder.Build();
},
lifetime));

return serviceCollection;
}
#else
public static IServiceCollection AddRabbitMQConnection(
this IServiceCollection serviceCollection,
Action<IConnectionBuilder> connectionBuilder,
ServiceLifetime lifetime = ServiceLifetime.Singleton)
{
serviceCollection.TryAdd(
new ServiceDescriptor(
typeof(IConnection),
sp =>
{
var builder = ConnectionBuilder.Default;
connectionBuilder(builder);
return builder.Build();
},
lifetime));

return serviceCollection;
}
#endif
}
10 changes: 7 additions & 3 deletions src/RabbitMQ.Next.Publisher/Publisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ private async Task InternalPublishAsync<TContent>(IMessageBuilder message, TCont
}
}



[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CheckDisposed()
{
Expand Down Expand Up @@ -185,7 +183,13 @@ private async ValueTask<IChannel> InitializeChannelAsync()
{
if (ch != null)
{
await ch.CloseAsync().ConfigureAwait(false);
try
{
await ch.CloseAsync().ConfigureAwait(false);
}
catch (Exception e)
{
}
}

throw;
Expand Down
5 changes: 5 additions & 0 deletions src/RabbitMQ.Next/Channels/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ public async ValueTask<ulong> PublishAsync<TContent>(
CancellationToken cancellation = default)
{
this.ValidateState();

if (this.serializer == null)
{
throw new InvalidOperationException("Cannot publish content when serializer was not set. Make sure serializer is configured correctly.");
}

var publishMethod = new PublishMethod(exchange, routingKey, (byte)flags);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class ConsumerBenchmarks
public async Task Setup()
{
this.connection = ConnectionBuilder.Default
.Endpoint(Helper.RabbitMqConnection)
.UseConnectionString(Helper.RabbitMqConnection)
.UsePlainTextSerializer()
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class PublishNoConfirmBenchmarks
public PublishNoConfirmBenchmarks()
{
this.connection = ConnectionBuilder.Default
.Endpoint(Helper.RabbitMqConnection)
.UseConnectionString(Helper.RabbitMqConnection)
.UsePlainTextSerializer()
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public PublisherBenchmarks()
this.theirConnection = factory.CreateConnection();

this.connection = ConnectionBuilder.Default
.Endpoint(Helper.RabbitMqConnection)
.UseConnectionString(Helper.RabbitMqConnection)
.UsePlainTextSerializer()
.Build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@ public void AddEndpointStringThrowsOnNonUri()
{
var builder = Substitute.For<IConnectionBuilder>();

Assert.Throws<ArgumentException>(() => builder.Endpoint("some random text"));
Assert.Throws<ArgumentException>(() => builder.UseConnectionString("some random text"));
}

[Fact]
public void AddEndpointStringThrowsOnNoAmqp()
{
var builder = Substitute.For<IConnectionBuilder>();

Assert.Throws<ArgumentException>(() => builder.Endpoint("http://rabbitmq.com"));
Assert.Throws<ArgumentException>(() => builder.UseConnectionString("http://rabbitmq.com"));
}

[Fact]
public void AddEndpointUriThrowsOnNoAmqp()
{
var builder = Substitute.For<IConnectionBuilder>();

Assert.Throws<ArgumentException>(() => builder.Endpoint(new Uri("http://rabbitmq.com")));
Assert.Throws<ArgumentException>(() => builder.UseConnectionString(new Uri("http://rabbitmq.com")));
}

[Theory]
Expand All @@ -50,7 +50,7 @@ public void AddEndpointCanParseValidUri(string endpoint, bool ssl, string host,
{
var builder = Substitute.For<IConnectionBuilder>();

builder.Endpoint(endpoint);
builder.UseConnectionString(endpoint);

builder.Received().Endpoint(host, port, ssl);
builder.Received().VirtualHost(vhost);
Expand Down

0 comments on commit 7d98af3

Please sign in to comment.