Skip to content

Commit 318fa1a

Browse files
committed
Exclude feature-specific exceptions from resilience policy retries
- MessageBusBase: Exclude MessageBusException from retries - CacheLockProvider: Exclude CacheException from retries - ResiliencePolicy: Add BrokenCircuitException to default unhandled exceptions - Update resilience documentation with new defaults These exceptions represent deliberate application-level failures that should not be retried by the resilience policy. Retrying them would be wasteful and could mask the underlying issue.
1 parent ae11694 commit 318fa1a

File tree

4 files changed

+18
-6
lines changed

4 files changed

+18
-6
lines changed

docs/guide/resilience.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,14 @@ var policy = new ResiliencePolicyBuilder()
151151

152152
### Unhandled Exceptions
153153

154+
By default, `OperationCanceledException` and `BrokenCircuitException` are never retried. You can add additional exception types:
155+
154156
```csharp
155157
var policy = new ResiliencePolicyBuilder()
156158
.WithMaxAttempts(5)
157159
// These exceptions will be thrown immediately without retry
158-
.WithUnhandledException<OperationCanceledException>()
159160
.WithUnhandledException<ArgumentException>()
161+
.WithUnhandledException<InvalidOperationException>()
160162
.Build();
161163
```
162164

@@ -581,6 +583,12 @@ public class MyService
581583
.WithUnhandledException<ArgumentException>()
582584
```
583585

586+
> **Note:** By default, `OperationCanceledException` and `BrokenCircuitException` are never retried. Additionally, Foundatio's built-in components automatically exclude their feature-specific exceptions from retries:
587+
> - `MessageBusBase` excludes `MessageBusException`
588+
> - `CacheLockProvider` excludes `CacheException`
589+
>
590+
> This ensures that deliberate application-level failures (like a blocked RabbitMQ connection or a cache operation error) are not wastefully retried.
591+
584592
### 5. Log Retry Attempts
585593

586594
```csharp

src/Foundatio/Lock/CacheLockProvider.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Concurrent;
33
using System.Diagnostics;
44
using System.Diagnostics.Metrics;
@@ -41,7 +41,9 @@ public CacheLockProvider(ICacheClient cacheClient, IMessageBus messageBus, TimeP
4141
_messageBus = messageBus;
4242

4343
_resiliencePolicyProvider = resiliencePolicyProvider ?? cacheClient.GetResiliencePolicyProvider();
44-
_resiliencePolicy = _resiliencePolicyProvider.GetPolicy<CacheLockProvider, ILockProvider>(_logger, _timeProvider);
44+
_resiliencePolicy = _resiliencePolicyProvider.GetPolicy<CacheLockProvider, ILockProvider>(
45+
builder => builder.WithUnhandledException<CacheException>(),
46+
_logger, _timeProvider);
4547

4648
_lockWaitTimeHistogram = FoundatioDiagnostics.Meter.CreateHistogram<double>("foundatio.lock.wait.time", description: "Time waiting for locks", unit: "ms");
4749
_lockTimeoutCounter = FoundatioDiagnostics.Meter.CreateCounter<int>("foundatio.lock.failed", description: "Number of failed attempts to acquire a lock");

src/Foundatio/Messaging/MessageBusBase.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ public MessageBusBase(TOptions options)
3535
_timeProvider = options.TimeProvider ?? TimeProvider.System;
3636

3737
_resiliencePolicyProvider = options.ResiliencePolicyProvider;
38-
_resiliencePolicy = _resiliencePolicyProvider.GetPolicy<MessageBusBase<TOptions>, IMessageBus>(_logger, _timeProvider);
38+
_resiliencePolicy = _resiliencePolicyProvider.GetPolicy<MessageBusBase<TOptions>, IMessageBus>(
39+
builder => builder.WithUnhandledException<MessageBusException>(),
40+
_logger, _timeProvider);
3941

4042
_serializer = options.Serializer ?? DefaultSerializer.Instance;
4143
MessageBusId = _options.Topic + Guid.NewGuid().ToString("N").Substring(10);

src/Foundatio/Resilience/ResiliencePolicy.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ public ILogger Logger
3939
public int MaxAttempts { get; set; } = 3;
4040

4141
/// <summary>
42-
/// A collection of exception types that will not be handled by the policy. These exceptions will be thrown immediately without retrying. Default includes OperationCanceledException.
42+
/// A collection of exception types that will not be handled by the policy. These exceptions will be thrown immediately without retrying. Default includes OperationCanceledException and BrokenCircuitException.
4343
/// </summary>
44-
public HashSet<Type> UnhandledExceptions { get; set; } = [typeof(OperationCanceledException)];
44+
public HashSet<Type> UnhandledExceptions { get; set; } = [typeof(OperationCanceledException), typeof(BrokenCircuitException)];
4545

4646
/// <summary>
4747
/// A function that determines whether to retry based on the attempt number and exception.

0 commit comments

Comments
 (0)