Retry Policies¶
Retry policies define how a subscriber can reprocess messages that fail during handling.
ServiceBus.Core.Rabbit implements subscriber retry by creating a RabbitMQ retry topology based on:
- a DLX exchange;
- a retry exchange;
- a retry queue;
- message TTL;
- dead-letter routing back to the main queue.
Retry Condition¶
A message enters the retry flow only when the message handler completes with:
args.Acknowledged = false;
args.Requeue = true;
If Acknowledged is true, the message is completed.
If Requeue is false, the message is not sent through the retry flow.
Retry Topology¶
When retry is enabled, the provider builds an auxiliary topology around the main queue.
graph LR
MainQueue["Main Queue"]
Subscriber["Subscriber"]
DlxExchange["DLX Exchange<br/>queue_dlx"]
RetryQueue["Retry Queue<br/>queue_retry"]
RetryExchange["Retry Exchange<br/>queue_retry"]
MainQueue --> Subscriber
Subscriber -->|"Acknowledged = false<br/>Requeue = true"| DlxExchange
DlxExchange --> RetryQueue
RetryQueue -->|"x-message-ttl expires"| RetryExchange
RetryExchange --> MainQueue
Generated Objects¶
The retry topology is created from the main queue.
If the queue logical name is:
orders.created
the retry infrastructure is derived using suffixes:
| Object | Suffix |
|---|---|
| DLX exchange | _dlx |
| Retry exchange | _retry |
| Retry queue | _retry |
Retry Queue Arguments¶
The retry queue is created with RabbitMQ arguments similar to:
Arguments =
{
["x-message-ttl"] = retryPolicy.Delayed.TotalMilliseconds,
["x-dead-letter-exchange"] = retryExchange.FullName,
["x-queue-type"] = queueType
};
Where x-queue-type is copied from the main queue when available.
If the main queue does not define a queue type, the retry queue uses:
classic
Binding Flow¶
The provider creates the following bindings:
DLX Exchange -> Retry Queue
Retry Exchange -> Main Queue
This creates a delayed retry loop:
Main Queue
-> Subscriber failure
-> DLX Exchange
-> Retry Queue
-> TTL expires
-> Retry Exchange
-> Main Queue
When Retry Is Useful¶
Retries are useful for transient failures, such as:
- temporary database unavailability;
- network interruptions;
- downstream service timeouts;
- temporary lock conflicts.
When Retry Is Not Useful¶
Retries are usually not useful for:
- invalid payloads;
- unsupported message versions;
- business validation failures;
- missing required data.
For these cases, set:
args.Acknowledged = false;
args.Requeue = false;
so the message is not sent back through the retry loop.