ToolsToLive.RabbitMQ
10.0.0
dotnet add package ToolsToLive.RabbitMQ --version 10.0.0
NuGet\Install-Package ToolsToLive.RabbitMQ -Version 10.0.0
<PackageReference Include="ToolsToLive.RabbitMQ" Version="10.0.0" />
<PackageVersion Include="ToolsToLive.RabbitMQ" Version="10.0.0" />
<PackageReference Include="ToolsToLive.RabbitMQ" />
paket add ToolsToLive.RabbitMQ --version 10.0.0
#r "nuget: ToolsToLive.RabbitMQ, 10.0.0"
#:package ToolsToLive.RabbitMQ@10.0.0
#addin nuget:?package=ToolsToLive.RabbitMQ&version=10.0.0
#tool nuget:?package=ToolsToLive.RabbitMQ&version=10.0.0
ToolsToLive.RabbitMQ
A .NET 10 library for routed messages, delayed delivery and publish/subscribe events over RabbitMQ. Messages are serialized as JSON, with enum values written as strings.
Versioning
Starting with 10.0.0, versions follow the same scheme as ToolsToLive.Logging: the first number is the supported .NET version, the second is the library major version, and the third is the library minor version.
Configuration
appsettings.json:
{
"RabbitMqSettings": {
"Host": "<rabbitmq-host>",
"Port": 5672,
"UserName": "<user>",
"Password": "<password>",
"AppName": "sample",
"AppVersion": "v1",
"UseBuiltInRecovery": true
}
}
Alternatively, replace Host, Port, UserName and Password with a connection string. URI-encode special characters in its credentials:
{
"RabbitMqSettings": {
"ConnectionString": "amqp://<user>:<password>@<rabbitmq-host>:5672/",
"AppName": "sample",
"AppVersion": "v1",
"UseBuiltInRecovery": true
}
}
| Setting | Purpose |
|---|---|
AppName, AppVersion |
Namespace for exchange and queue names. Participants exchanging messages must use the same values. Changing them targets different queues. |
NameDelimiter, SkipNameSuffix |
Control generated names; keep them consistent across participants. Defaults: - and false. |
ConsumerDispatchConcurrency |
Concurrent dispatch per channel; defaults to 1. Higher values require thread-safe handlers and remove the processing-order guarantee. |
UseBuiltInRecovery |
Enables RabbitMQ.Client connection, channel and topology recovery instead of the library's custom consumer recovery. Defaults to false; enabled explicitly above. |
See RabbitMqSettings.cs for all settings, including TLS and delay durations. Supply real credentials through your application's configuration providers rather than committing them.
Startup and routes
ASP.NET Core Program.cs:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using ToolsToLive.RabbitMQ;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRabbitMqMessageHandler(
builder.Configuration.GetSection("RabbitMqSettings"));
builder.Services.AddHostedService<MessageConsumer>();
var app = builder.Build();
await app.Services.ConfigureRabbitMQAsync<Routes>();
await app.RunAsync();
ConfigureRabbitMQAsync<TRoute> creates the exchanges, delay queues and one queue for each value of the route enum. Call it before sending messages or starting listeners; the broker must be available. EventBus uses the same exchange, so it also needs this initialization. An EventBus-only application can use an empty route enum.
Shared contracts used by the examples:
public enum Routes
{
SendModel
}
public sealed class Model
{
public string SomeField { get; set; } = "";
}
public sealed class SomethingCreatedEvent
{
public int Id { get; set; }
}
With the configuration above, the exchange is sample-v1-exchange and the route queue is sample-v1-send-model-queue. Producers and consumers must agree on route names and message contracts.
Sending messages
Inject IMessageSender into an application service:
using ToolsToLive.RabbitMQ.Interfaces;
using ToolsToLive.RabbitMQ.Model;
public sealed class MessagePublisher(IMessageSender sender)
{
public Task SendAsync(CancellationToken cancellationToken = default)
{
var message = new Model { SomeField = "Some content" };
return sender.SendAsync(message, Routes.SendModel, cancellationToken);
}
public Task SendLaterAsync(CancellationToken cancellationToken = default)
{
var message = new Model { SomeField = "Some content" };
return sender.SendAsync(message, Routes.SendModel, SendingDelay.Delay4,
cancellationToken);
}
}
Delay4 defaults to five minutes and is configured by RabbitMqSettings.Delay4. Delayed messages pass through TTL/dead-letter queues; no delayed-message plugin is required. Successful sending does not mean the consumer has finished processing.
Receiving messages
The hosted service registered at startup keeps its listener until the application stops:
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ToolsToLive.RabbitMQ.Interfaces;
public sealed class MessageConsumer(
IMessageListenerFactory listenerFactory,
ILogger<MessageConsumer> logger) : IHostedService
{
private IMessageListener? _listener;
public async Task StartAsync(CancellationToken cancellationToken)
{
_listener = await listenerFactory.CreateAndStartListeningAsync<Routes, Model>(
Routes.SendModel, HandleAsync, prefetchCount: 5,
cancellationToken: cancellationToken);
}
public async Task StopAsync(CancellationToken cancellationToken)
{
if (_listener is not null)
await _listener.DisposeAsync();
}
private Task HandleAsync(Model message)
{
logger.LogInformation("Received {SomeField}", message.SomeField);
return Task.CompletedTask;
}
}
prefetchCount limits unacknowledged messages per listener; it does not set processing concurrency. The callback is Func<TMessage, Task> and receives no cancellation token. Resolve scoped application services in a separate DI scope per message.
Deserialization and handler exceptions are logged, and the message is then acknowledged. Throwing from the handler does not trigger redelivery; implement retries in the application if needed. Handlers should also tolerate duplicate deliveries, for example after a connection failure before acknowledgement.
EventBus
Inject IEventBus to publish events:
using ToolsToLive.RabbitMQ.Interfaces;
public sealed class EventPublisher(IEventBus eventBus)
{
public Task PublishAsync(int id, CancellationToken cancellationToken = default)
{
return eventBus.PublishAsync("something_created",
new SomethingCreatedEvent { Id = id }, cancellationToken);
}
}
To receive events, add builder.Services.AddHostedService<EventConsumer>(); before builder.Build():
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ToolsToLive.RabbitMQ.Interfaces;
using ToolsToLive.RabbitMQ.Model;
public sealed class EventConsumer(
IEventBus eventBus,
ILogger<EventConsumer> logger) : IHostedService
{
private Subscription? _subscription;
public async Task StartAsync(CancellationToken cancellationToken)
{
_subscription = await eventBus.SubscribeAsync<SomethingCreatedEvent>(
"something_created", "app1", HandleAsync, prefetchCount: 1,
cancellationToken: cancellationToken);
}
public async Task StopAsync(CancellationToken cancellationToken)
{
if (_subscription is not null)
await _subscription.DisposeAsync();
}
private Task HandleAsync(SomethingCreatedEvent message)
{
logger.LogInformation("Something created: {Id}", message.Id);
return Task.CompletedTask;
}
}
SubscribeAsync creates and binds a durable queue. Different appKey values, such as app1 and app2, get separate queues and each receives a copy of the event. Subscribers with the same key share a queue and compete for its messages. Keep event names and keys consistent in spelling and case.
Keep the subscription alive while receiving events. DisposeAsync (or UnsubscribeAsync) stops listening and keeps the queue and pending messages for the next start. DeleteQueueAsync(eventType, appKey) deletes the queue and its messages; use it only when permanently removing a subscription. Only queues already bound at publication receive an event.
Health checks and tracing
After registering the library, add a health check with builder.Services.AddHealthChecks().AddRabbitMQ(); (namespace ToolsToLive.RabbitMQ.HealthCheck). It checks the connection by opening a channel; it does not verify message processing.
For OpenTelemetry tracing, include ToolsToLive.RabbitMQ.Observability.Tracing.ActivitySourceName in your tracer provider's AddSource(...) configuration. The library emits producer/consumer activities and propagates trace context through message headers.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.15)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.15)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.15)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.15)
- Newtonsoft.Json (>= 13.0.4)
- OpenTelemetry (>= 1.20.0)
- RabbitMQ.Client (>= 7.2.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.0 | 0 | 11/13/2026 |
| 4.0.0 | 17,765 | 4/22/2026 |
| 4.0.0-alpha.66 | 166 | 4/17/2026 |
| 3.0.0 | 4,537 | 11/20/2025 |
| 2.3.0 | 3,261 | 8/8/2025 |
| 2.2.1 | 283 | 8/8/2025 |
| 2.2.0 | 1,079 | 6/27/2025 |
| 2.1.0 | 821 | 3/15/2025 |
| 2.0.0 | 219 | 2/26/2025 |
| 1.3.1 | 239 | 4/15/2024 |
| 1.3.0 | 8,298 | 12/2/2023 |
| 1.2.0 | 840 | 11/22/2023 |
| 1.1.0 | 5,420 | 11/8/2022 |
| 1.1.0-alpha.15 | 255 | 11/8/2022 |
| 1.0.1-alpha.10 | 563 | 3/21/2022 |
| 1.0.1-alpha.7 | 303 | 3/20/2022 |