Lyo.MessageQueue.RabbitMq
1.0.6
dotnet add package Lyo.MessageQueue.RabbitMq --version 1.0.6
NuGet\Install-Package Lyo.MessageQueue.RabbitMq -Version 1.0.6
<PackageReference Include="Lyo.MessageQueue.RabbitMq" Version="1.0.6" />
<PackageVersion Include="Lyo.MessageQueue.RabbitMq" Version="1.0.6" />
<PackageReference Include="Lyo.MessageQueue.RabbitMq" />
paket add Lyo.MessageQueue.RabbitMq --version 1.0.6
#r "nuget: Lyo.MessageQueue.RabbitMq, 1.0.6"
#:package Lyo.MessageQueue.RabbitMq@1.0.6
#addin nuget:?package=Lyo.MessageQueue.RabbitMq&version=1.0.6
#tool nuget:?package=Lyo.MessageQueue.RabbitMq&version=1.0.6
Lyo.MessageQueue.RabbitMq
IMqService implementation (RabbitMqService) on RabbitMQ.Client. Also registered as IRabbitMqService when you need RabbitMQ-specific methods (exchanges) that are not part of the shared contract.
Features
RabbitMqOptionssingleton (registered via an explicitAction<RabbitMqOptions>or bound from configuration). Default section name:RabbitMqOptions.SectionName = "RabbitMqOptions".IConnectionFactorysingleton built from those options with:- Host / virtual host / port / credentials from options.
ClientProvidedNameset toMachineName - ApplicationName (EnvironmentName)so the connection is identifiable in the RabbitMQ management UI.ClientPropertiespopulated from theconnectionPropertiesdictionary you pass to the extension (container id, build sha, and similar keys).RabbitMqServiceregistered as a singleton, exposed under all three types: itself,IRabbitMqService, andIMqService.
Examples
Register services
services.SetupRabbitMqServiceFromConfiguration(
builder.Configuration,
connectionProperties: new Dictionary<string, object?> { ["build_sha"] = buildSha });
// or
services.SetupRabbitMqService(
connectionProperties: [],
options =>
{
options.Host = "rabbit.internal";
options.Port = 5672;
options.VirtualHost = "/";
options.AdminUrl = "http://rabbit.internal:15672";
options.Username = "...";
options.Password = "...";
});
Registration
RabbitMqOptionssingleton (registered via an explicitAction<RabbitMqOptions>or bound from configuration). Default section name:RabbitMqOptions.SectionName = "RabbitMqOptions".IConnectionFactorysingleton built from those options with:- Host / virtual host / port / credentials from options.
ClientProvidedNameset toMachineName - ApplicationName (EnvironmentName)so the connection is identifiable in the RabbitMQ management UI.ClientPropertiespopulated from theconnectionPropertiesdictionary you pass to the extension (container id, build sha, and similar keys).RabbitMqServiceregistered as a singleton, exposed under all three types: itself,IRabbitMqService, andIMqService.
RabbitMqOptions
| Property | Type | Default | Purpose |
|---|---|---|---|
Host |
string |
required | AMQP host name. |
Port |
int |
5672 |
AMQP port. |
VirtualHost |
string |
/ |
RabbitMQ vhost. |
Username / Password |
string |
required | AMQP and Management API credentials. |
AdminUrl |
string |
required | Base URL of the RabbitMQ Management HTTP API (e.g. http://host:15672). Used to construct HttpClient.BaseAddress = "{AdminUrl}/api/"; ClearQueue, PeekQueueMessages, and the queue-statistics APIs call into it. |
EnableMetrics |
bool |
false |
When false, the injected IMetrics is replaced with NullMetrics.Instance. |
ProcessingLimit |
int |
0 |
Global maximum concurrent messages per queue. 0 means no limit. Enforced as broker prefetch + channel dispatch concurrency + in-process semaphore (see below). |
QueueProcessingLimits |
Dictionary<string, int>? |
null |
Per-queue overrides of ProcessingLimit (queue name → limit). Example: { "job.run.cs": 1, "job.run.reports": 10 }. |
PersistentMessages |
bool |
true |
Publish with delivery mode 2 so messages survive broker restarts on durable queues. |
PublisherConfirms |
bool |
false |
Confirm mode on the publish channel: SendToQueue/SendToExchange return true only after broker confirmation and false on nack (metric mq.publish.unconfirmed). Adds a round-trip per publish. |
AutomaticRecovery |
bool |
true |
RabbitMQ client automatic connection + topology recovery (restores channels and consumers after a network drop). |
NetworkRecoveryInterval |
TimeSpan |
5s |
Delay between automatic recovery attempts. |
ConnectRetryCount |
int |
3 |
Extra connect attempts inside ConnectAsync for startup races (broker not accepting connections yet). 0 fails on the first error. |
ConnectRetryDelay |
TimeSpan |
2s |
Delay between connect attempts. |
DefinedQueues |
IReadOnlyList<string>? |
null |
Queues to declare on ConnectAsync. |
ExceptionHandling |
MessageProcessingExceptionHandling |
RequeueOnException |
Strategy applied when a subscribed handler throws. ThrowAndRemoveFromQueue acks the message and rethrows the exception (routed to the client's callback exception handler). |
Per-queue concurrency
SubscribeToQueue resolves the queue's limit (QueueProcessingLimits[queue], falling back to
ProcessingLimit; 0 = unlimited) and enforces it at three levels:
- Broker prefetch.
BasicQosAsync(0, limit, false)on the dedicated subscription channel, so the broker only deliverslimitunacked messages to this consumer. Real backpressure: excess messages stay on the server and are available to other consumers. - Channel dispatch concurrency. The subscription channel is created with
consumerDispatchConcurrency = limit, so the client actually runs up tolimithandler invocations in parallel (the RabbitMQ.Client 7.x default is 1, i.e. strictly sequential). - In-process semaphore. A
SemaphoreSlim(limit)guards handler execution as a final in-process guarantee.
"RabbitMqOptions": {
"ProcessingLimit": 5,
"QueueProcessingLimits": { "job.run.cs": 1, "job.run.reports": 10 }
}
flowchart LR
broker[RabbitMQ broker] -->|"prefetch = per-queue limit"| channel[Dedicated channel]
channel -->|"dispatch concurrency = limit"| handler[Handler xN]
handler -->|ack / counted requeue| broker
conn[Connection drop] -->|automatic recovery| broker
Connection recovery
With AutomaticRecovery on (the default), the RabbitMQ client reconnects after a network drop, re-opens channels, re-declares topology, and restores consumers. The service keeps its consumer bookkeeping across the drop and logs/metrics the transition (mq.connection.lost then mq.connection.recovered). With recovery disabled, a lost connection clears all consumers. The process must reconnect and resubscribe itself. DisconnectAsync no longer poisons the instance: connect, disconnect, connect on the same RabbitMqService works. Disposal (DisposeAsync) is final.
Delayed messages
SendToQueueDelayed(queueName, data, delay) (on IRabbitMqService, also exposed through the
IDelayedMqService capability interface in Lyo.MessageQueue) delivers a message after a delay with no
broker plugin. The message is published to a companion wait queue {queue}.wait declared with
x-dead-letter-exchange: "" / x-dead-letter-routing-key: {queue} and a per-message TTL equal to the
delay. When the TTL fires, the broker dead-letters the message onto the real queue. Wait-queue
declarations are cached per service instance. QueueWorkerBase uses this automatically for retry backoff
when its RequeueDelay is set (see the Lyo.MessageQueue README).
Note: TTL expiry is FIFO per wait queue. A long-delay message queued ahead of a short-delay one delays the latter. For the retry-backoff use case (delays in the same order of magnitude) this is fine.
Broker-level DLQ auto-wiring
CreateQueueWithDlq(queueName, durable, dlqName, arguments, ct) declares {queue}.dlq (durable) and the main queue with x-dead-letter-exchange: "" / x-dead-letter-routing-key: {queue}.dlq. This catches broker-side rejections the application never sees: nack without requeue, per-queue TTL expiry, and queue overflow. It complements (does not replace) QueueWorkerBase's application-level DLQ routing. > Caveat: RabbitMQ cannot change arguments on an existing queue. Declaring over an existing queue with different arguments fails with PRECONDITION_FAILED. The helper logs a clear error telling you to delete and recreate the queue.
Queue statistics
GetQueueInfoAsync(queueName, ct) and GetAllQueuesInfoAsync(ct) (on IRabbitMqService) query the Management API (GET /api/queues/{vhost}[/{name}]) and return the shared MessageQueueInfo record. Message counts, ready/unacked, consumer count, state, plus publish/deliver rates in AdditionalProperties when the broker reports them. The RabbitMqWorkbench Blazor component shows these in its Stats tab. Statistics update on the management emission interval (~5s), so counts can lag slightly behind broker state.
Capabilities
| Abstract call | RabbitMQ behavior |
|---|---|
CreateQueue |
Declares queues with durability / exclusivity / auto-delete flags plus a broker arguments dictionary. |
DeleteQueue |
Deletes a queue, optionally guarded by ifUnused / ifEmpty. |
ClearQueue |
Purges first via the Management API (DELETE /api/queues/{vhost}/{name}/contents), falling back to QueuePurgeAsync on the publish channel. |
BindQueueToExchange |
Binds queue ↔ exchange with a routing key. |
SendToQueue / SendToExchange |
Publish on the shared publish channel with BasicProperties (persistence per PersistentMessages, generated MessageId, UTC timestamp); awaits broker confirmation when PublisherConfirms is on. |
SubscribeToQueue |
Opens a dedicated channel per subscriber (prefetch + dispatch concurrency from the per-queue limit), declares the queue, creates an AsyncEventingBasicConsumer, and bridges ack/nack/requeue to the Func<byte[], Task<bool>> contract (true → requeue, false → ack). |
PeekQueueMessages |
Non-destructive read via the Management API (POST /api/queues/{vhost}/{name}/get with ackmode=ack_requeue_true). |
CreateExchange / DeleteExchange (RabbitMQ only, on IRabbitMqService) |
Direct exchange declaration / deletion. |
SendToQueueDelayed (RabbitMQ only) |
Delayed delivery via TTL + dead-letter wait queues (see below). |
CreateQueueWithDlq (RabbitMQ only) |
Declares {queue}.dlq and wires the main queue's dead-letter arguments (see below). |
GetQueueInfoAsync / GetAllQueuesInfoAsync (RabbitMQ only) |
Live queue statistics via the Management API (see below). |
Because Rabbit features evolve quickly (streams, quorum queues), anything advanced tends to go through
CreateQueue's arguments bag. Inspect RabbitMqService for the defaults you rely on before upgrading
RabbitMQ.Client.
Hosted services and workers
Pair with QueueWorkerBase from Lyo.MessageQueue. Workers deserialize JSON payloads, reuse the envelope helpers, integrate DLQ / maxRequeueCount, and drain on IHostedService shutdown. Publish typed payloads with IMqService.SendToQueueWithEnvelopeAsync when a QueueWorkerBase consumer is on the other end. Schedulers (Lyo.Job.Scheduler) commonly publish triggers here while separate worker processes consume.
Blazor tooling
Lyo.MessageQueue.RabbitMq.Web.Components adds a UI on the same service registrations for internal dashboards.
Testing
Lyo.MessageQueue.RabbitMq.Tests runs the service against a real broker using the RabbitMqTestContainer helper from Lyo.Testing.Containers (management-enabled image, Docker required): connect/disconnect/reconnect, queue lifecycle + peek, publish→subscribe roundtrips, requeue/ack semantics, per-queue concurrency enforcement, publisher confirms, delayed delivery, DLQ auto-wiring, and queue statistics.
See also
Lyo.MessageQueue. The underlying contract, envelopes, and worker base.Lyo.Result. Worker results and theMetadata["requeue"]pattern.Lyo.Metrics. Counters and timers emitted by the service andQueueWorkerBase.Lyo.Testing.Containers. RabbitMQ testcontainer and fixture for integration tests.
Dependencies
Generated from ProjectReference / PackageReference (same model as docs/Lyo.ProjectGraph.html).
Lyo.Common(direct, lyo)Lyo.Exceptions(direct, lyo)Lyo.MessageQueue(direct, lyo)Lyo.Metrics(direct, lyo)Microsoft.Extensions.Configuration.Binder10.0.5(direct, microsoft)RabbitMQ.Client7.2.1(direct, third-party)System.Text.Json10.0.5(direct, microsoft, netstandard2.0)Lyo.Health(transitive, lyo)Lyo.Result(transitive, lyo)Microsoft.Extensions.DependencyInjection.Abstractions10.0.5(transitive, microsoft)Microsoft.Extensions.Hosting.Abstractions10.0.5(transitive, microsoft)Microsoft.Extensions.Logging.Abstractions10.0.5(transitive, microsoft)Microsoft.Extensions.Options.ConfigurationExtensions10.0.5(transitive, microsoft)System.Memory4.6.3(transitive, microsoft, netstandard2.0)
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Lyo.Common (>= 1.0.6)
- Lyo.Exceptions (>= 1.0.6)
- Lyo.MessageQueue (>= 1.0.6)
- Lyo.Metrics (>= 1.0.6)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.5)
- RabbitMQ.Client (>= 7.2.1)
- System.Text.Json (>= 10.0.5)
-
net10.0
- Lyo.Common (>= 1.0.6)
- Lyo.Exceptions (>= 1.0.6)
- Lyo.MessageQueue (>= 1.0.6)
- Lyo.Metrics (>= 1.0.6)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.5)
- RabbitMQ.Client (>= 7.2.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Lyo.MessageQueue.RabbitMq:
| Package | Downloads |
|---|---|
|
Lyo.MessageQueue.RabbitMq.Web.Components
Reusable Blazor components for RabbitMQ-specific exchanges, bindings, and broker workbenches. |
GitHub repositories
This package is not used by any popular GitHub repositories.