Skip to content

Commit c216415

Browse files
committed
More tests
1 parent dcafa9d commit c216415

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

src/Foundatio/Utility/ResiliencePipeline.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ public FoundatioResiliencePipeline(TimeProvider timeProvider = null, ILogger log
102102
{
103103
_timeProvider = timeProvider ?? TimeProvider.System;
104104
_logger = logger ?? NullLogger.Instance;
105-
106-
MaxAttempts = 5;
107-
RetryInterval = null;
108105
}
109106

110107
/// <summary>
@@ -123,7 +120,7 @@ public ILogger Logger {
123120
/// <summary>
124121
/// The maximum number of attempts to execute the action.
125122
/// </summary>
126-
public int MaxAttempts { get; set; }
123+
public int? MaxAttempts { get; set; }
127124

128125
/// <summary>
129126
/// A function that determines whether to retry based on the attempt number and exception.
@@ -152,6 +149,7 @@ public async ValueTask ExecuteAsync(Func<CancellationToken, ValueTask> action, C
152149

153150
cancellationToken.ThrowIfCancellationRequested();
154151

152+
int maxAttempts = MaxAttempts ?? (ShouldRetry != null ? Int32.MaxValue : 5);
155153
int attempts = 1;
156154
var startTime = _timeProvider.GetUtcNow();
157155
var linkedCancellationToken = cancellationToken;
@@ -170,7 +168,7 @@ public async ValueTask ExecuteAsync(Func<CancellationToken, ValueTask> action, C
170168
}
171169
catch (Exception ex)
172170
{
173-
if ((ShouldRetry != null && !ShouldRetry(attempts, ex)) || attempts >= MaxAttempts)
171+
if ((ShouldRetry != null && !ShouldRetry(attempts, ex)) || attempts >= maxAttempts)
174172
throw;
175173

176174
_logger?.LogError(ex, "Retry error: {Message}", ex.Message);
@@ -181,7 +179,7 @@ public async ValueTask ExecuteAsync(Func<CancellationToken, ValueTask> action, C
181179
}
182180

183181
attempts++;
184-
} while (attempts <= MaxAttempts && !linkedCancellationToken.IsCancellationRequested);
182+
} while (attempts <= maxAttempts && !linkedCancellationToken.IsCancellationRequested);
185183

186184
throw new TaskCanceledException("Should not get here");
187185
}
@@ -193,6 +191,7 @@ public async ValueTask<T> ExecuteAsync<T>(Func<CancellationToken, ValueTask<T>>
193191

194192
cancellationToken.ThrowIfCancellationRequested();
195193

194+
int maxAttempts = MaxAttempts ?? (ShouldRetry != null ? Int32.MaxValue : 5);
196195
int attempts = 1;
197196
var startTime = _timeProvider.GetUtcNow();
198197
var linkedCancellationToken = cancellationToken;
@@ -210,7 +209,7 @@ public async ValueTask<T> ExecuteAsync<T>(Func<CancellationToken, ValueTask<T>>
210209
}
211210
catch (Exception ex)
212211
{
213-
if ((ShouldRetry != null && !ShouldRetry(attempts, ex)) || attempts >= MaxAttempts)
212+
if ((ShouldRetry != null && !ShouldRetry(attempts, ex)) || attempts >= maxAttempts)
214213
throw;
215214

216215
_logger?.LogError(ex, "Retry error: {Message}", ex.Message);
@@ -221,7 +220,7 @@ public async ValueTask<T> ExecuteAsync<T>(Func<CancellationToken, ValueTask<T>>
221220
}
222221

223222
attempts++;
224-
} while (attempts <= MaxAttempts && !linkedCancellationToken.IsCancellationRequested);
223+
} while (attempts <= maxAttempts && !linkedCancellationToken.IsCancellationRequested);
225224

226225
throw new TaskCanceledException("Should not get here");
227226
}

tests/Foundatio.Tests/Utility/ResiliencePipelineTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,43 @@ public async Task CanBoomWithRetriesAndResult()
129129
Assert.Equal(1, result);
130130
}
131131

132+
[Fact]
133+
public async Task CanHandleSpecificExceptions()
134+
{
135+
var pipeline = new FoundatioResiliencePipeline
136+
{
137+
Logger = _logger,
138+
RetryInterval = TimeSpan.Zero,
139+
ShouldRetry = (attempts, ex) => attempts < 3 && ex is ApplicationException,
140+
};
141+
142+
int attempt = 0;
143+
var exception = await Assert.ThrowsAsync<ApplicationException>(async () =>
144+
{
145+
await pipeline.ExecuteAsync(() =>
146+
{
147+
attempt++;
148+
throw new ApplicationException("Simulated failure");
149+
}, cancellationToken: CancellationToken.None);
150+
});
151+
152+
Assert.Equal("Simulated failure", exception.Message);
153+
Assert.Equal(3, attempt);
154+
155+
attempt = 0;
156+
var argumentException = await Assert.ThrowsAsync<ArgumentException>(async () =>
157+
{
158+
await pipeline.ExecuteAsync(() =>
159+
{
160+
attempt++;
161+
throw new ArgumentException("Unhandled exception type");
162+
}, cancellationToken: CancellationToken.None);
163+
});
164+
165+
Assert.Equal("Unhandled exception type", argumentException.Message);
166+
Assert.Equal(1, attempt);
167+
}
168+
132169
[Fact]
133170
public async Task CanRunWithRetriesAndCancellation()
134171
{

0 commit comments

Comments
 (0)