Skip to content

Commit 784f9b0

Browse files
authored
feat!: remove the exponentialWithJitter case (#71)
* feat!: remove the `exponentialWithJitter` case * docs: update the documentation
1 parent 5e7e30c commit 784f9b0

9 files changed

Lines changed: 27 additions & 49 deletions

File tree

CONTRIBUTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ When creating a bug report, include:
7979
**Title:** ExponentialWithJitter strategy returns incorrect delay
8080

8181
**Steps to reproduce:**
82-
1. Create RetryPolicyService with exponentialWithJitter strategy
82+
1. Create RetryPolicyService with exponential strategy
8383
2. Set maxInterval to 30 seconds
8484
3. Observe delays exceeding maxInterval
8585

@@ -94,7 +94,7 @@ When creating a bug report, include:
9494
**Code:**
9595
\`\`\`swift
9696
let service = RetryPolicyService(
97-
strategy: .exponentialWithJitter(
97+
strategy: .exponential(
9898
retry: 5,
9999
maxInterval: .seconds(30),
100100
duration: .seconds(1)
@@ -219,7 +219,7 @@ Closes #45
219219

220220
---
221221

222-
fix(strategy): correct maxInterval comparison in exponentialWithJitter
222+
fix(strategy): correct maxInterval comparison in exponential
223223

224224
maxInterval was compared in seconds instead of nanoseconds, causing
225225
delays to be capped incorrectly. Now properly converts maxInterval
@@ -515,4 +515,4 @@ Contributors are recognized in:
515515

516516
Thank you for contributing to Typhoon! 🎉
517517

518-
Your efforts help make this project better for everyone.
518+
Your efforts help make this project better for everyone.

README.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,8 @@ Typhoon provides three powerful retry strategies to handle different failure sce
101101
/// A retry strategy with a constant number of attempts and fixed duration between retries.
102102
case constant(retry: Int, duration: DispatchTimeInterval)
103103

104-
/// A retry strategy with an exponential increase in duration between retries.
105-
case exponential(retry: Int, multiplier: Double = 2.0, duration: DispatchTimeInterval)
106-
107104
/// A retry strategy with exponential increase in duration between retries and added jitter.
108-
case exponentialWithJitter(
105+
case exponential(
109106
retry: Int,
110107
jitterFactor: Double = 0.1,
111108
maxInterval: DispatchTimeInterval? = .seconds(60),
@@ -182,7 +179,7 @@ import Typhoon
182179

183180
// Retry with exponential backoff, jitter, and maximum interval cap
184181
let service = RetryPolicyService(
185-
strategy: .exponentialWithJitter(
182+
strategy: .exponential(
186183
retry: 5,
187184
jitterFactor: 0.2, // Add ±20% randomization
188185
maxInterval: .seconds(30), // Cap at 30 seconds
@@ -235,7 +232,7 @@ import Typhoon
235232

236233
class DatabaseManager {
237234
private let retryService = RetryPolicyService(
238-
strategy: .exponentialWithJitter(
235+
strategy: .exponential(
239236
retry: 5,
240237
jitterFactor: 0.15,
241238
maxInterval: .seconds(60),
@@ -332,4 +329,4 @@ Typhoon is released under the MIT license. See [LICENSE](https://github.com/spac
332329

333330
Made with ❤️ by [space-code](https://github.com/space-code)
334331

335-
</div>
332+
</div>

Sources/Typhoon/Classes/RetrySequence/Iterator/RetryIterator.swift

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,7 @@ struct RetryIterator: IteratorProtocol {
8686
case let .constant(_, duration):
8787
convertToNanoseconds(duration)
8888

89-
case let .exponential(_, multiplier, duration):
90-
calculateExponentialDelay(
91-
duration: duration,
92-
multiplier: multiplier,
93-
retries: retries
94-
)
95-
96-
case let .exponentialWithJitter(_, jitterFactor, maxInterval, multiplier, duration):
89+
case let .exponential(_, jitterFactor, maxInterval, multiplier, duration):
9790
calculateExponentialDelayWithJitter(
9891
duration: duration,
9992
multiplier: multiplier,

Sources/Typhoon/Classes/Strategy/RetryPolicyStrategy.swift

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ public enum RetryPolicyStrategy: Sendable {
1414
/// - duration: The initial duration between retries.
1515
case constant(retry: Int, duration: DispatchTimeInterval)
1616

17-
/// A retry strategy with an exponential increase in duration between retries.
18-
///
19-
/// - Parameters:
20-
/// - retry: The number of retry attempts.
21-
/// - multiplier: The multiplier for calculating the exponential backoff duration (default is 2).
22-
/// - duration: The initial duration between retries.
23-
case exponential(retry: Int, multiplier: Double = 2, duration: DispatchTimeInterval)
24-
2517
/// A retry strategy with exponential increase in duration between retries and added jitter.
2618
///
2719
/// - Parameters:
@@ -30,7 +22,7 @@ public enum RetryPolicyStrategy: Sendable {
3022
/// - maxInterval: The maximum allowed interval between retries (default is 60 seconds).
3123
/// - multiplier: The multiplier for calculating the exponential backoff duration (default is 2).
3224
/// - duration: The initial duration between retries.
33-
case exponentialWithJitter(
25+
case exponential(
3426
retry: Int,
3527
jitterFactor: Double = 0.1,
3628
maxInterval: DispatchTimeInterval? = .seconds(60),
@@ -43,9 +35,7 @@ public enum RetryPolicyStrategy: Sendable {
4335
switch self {
4436
case let .constant(retry, _):
4537
retry
46-
case let .exponential(retry, _, _):
47-
retry
48-
case let .exponentialWithJitter(retry, _, _, _, _):
38+
case let .exponential(retry, _, _, _, _):
4939
retry
5040
}
5141
}
@@ -55,9 +45,7 @@ public enum RetryPolicyStrategy: Sendable {
5545
switch self {
5646
case let .constant(_, duration):
5747
duration
58-
case let .exponential(_, _, duration):
59-
duration
60-
case let .exponentialWithJitter(_, _, _, _, duration):
48+
case let .exponential(_, _, _, _, duration):
6149
duration
6250
}
6351
}

Sources/Typhoon/Typhoon.docc/Articles/advanced-retry-strategies.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ let strategy = RetryStrategy.exponential(
8080
When multiple clients retry simultaneously, they can overwhelm a recovering service. Jitter adds randomization to prevent this:
8181

8282
```swift
83-
let strategy = RetryStrategy.exponentialWithJitter(
83+
let strategy = RetryStrategy.exponential(
8484
retry: 5, // 5 retry attempts
8585
jitterFactor: 0.2, // ±20% randomization
8686
maxInterval: .seconds(30), // Cap at 30 seconds
@@ -110,7 +110,7 @@ Traffic spread out! ✅
110110
Prevent delays from growing unbounded:
111111

112112
```swift
113-
.exponentialWithJitter(
113+
.exponential(
114114
retry: 10, // 10 retry attempts = 11 total
115115
jitterFactor: 0.1,
116116
maxInterval: .seconds(60), // Never wait more than 60 seconds
@@ -235,7 +235,7 @@ actor AdaptiveRetryService {
235235
if consecutiveFailures >= maxConsecutiveFailures {
236236
// System under stress - use conservative strategy
237237
// 1 initial + 3 retries with longer delays
238-
return .exponentialWithJitter(
238+
return .exponential(
239239
retry: 3,
240240
jitterFactor: 0.3,
241241
maxInterval: 120,

Sources/Typhoon/Typhoon.docc/Articles/best-practices.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ let apiRetry = RetryPolicyService(
2525

2626
// ✅ High-traffic services
2727
let highTrafficRetry = RetryPolicyService(
28-
strategy: .exponentialWithJitter(
28+
strategy: .exponential(
2929
retry: 5,
3030
jitterFactor: 0.2,
3131
maxInterval: 60,
@@ -102,7 +102,7 @@ class NetworkRetryService {
102102
)
103103

104104
static let critical = RetryPolicyService(
105-
strategy: .exponentialWithJitter(
105+
strategy: .exponential(
106106
retry: 5,
107107
jitterFactor: 0.2,
108108
maxInterval: 60,
@@ -193,7 +193,7 @@ let badService = RetryPolicyService(
193193

194194
// ✅ Good - Reasonable limits
195195
let goodService = RetryPolicyService(
196-
strategy: .exponentialWithJitter(
196+
strategy: .exponential(
197197
retry: 5,
198198
maxInterval: 60,
199199
duration: .seconds(1)

Sources/Typhoon/Typhoon.docc/Articles/quick-start.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Best for preventing thundering herd problems:
9393

9494
```swift
9595
// Retry with exponential backoff, jitter, and cap
96-
.exponentialWithJitter(
96+
.exponential(
9797
retry: 5,
9898
jitterFactor: 0.2,
9999
maxInterval: .seconds(30),
@@ -166,7 +166,7 @@ let networkRetry = RetryPolicyService(
166166

167167
// Critical operations (payments, data persistence)
168168
let criticalRetry = RetryPolicyService(
169-
strategy: .exponentialWithJitter(
169+
strategy: .exponential(
170170
retry: 5,
171171
jitterFactor: 0.15,
172172
maxInterval: .seconds(60),

Tests/TyphoonTests/UnitTests/RetryPolicyStrategyTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ final class RetryPolicyStrategyTests: XCTestCase {
2929

3030
func test_thatRetryPolicyStrategyReturnsDuration_whenTypeIsExponentialWithJitter() {
3131
// when
32-
let duration = RetryPolicyStrategy.exponentialWithJitter(retry: .retry, duration: .second).duration
32+
let duration = RetryPolicyStrategy.exponential(retry: .retry, duration: .second).duration
3333

3434
// then
3535
XCTAssertEqual(duration, .second)

Tests/TyphoonTests/UnitTests/RetrySequenceTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ final class RetrySequenceTests: XCTestCase {
2424

2525
func test_thatRetrySequenceCreatesASequence_whenStrategyIsExponential() {
2626
// given
27-
let sequence = RetrySequence(strategy: .exponential(retry: .retry, duration: .nanosecond))
27+
let sequence = RetrySequence(strategy: .exponential(retry: .retry, jitterFactor: .zero, duration: .nanosecond))
2828

2929
// when
3030
let result: [UInt64] = sequence.map { $0 }
@@ -40,7 +40,7 @@ final class RetrySequenceTests: XCTestCase {
4040
let jitterFactor = 0.1
4141

4242
let sequence = RetrySequence(
43-
strategy: .exponentialWithJitter(
43+
strategy: .exponential(
4444
retry: 5,
4545
jitterFactor: jitterFactor,
4646
maxInterval: nil,
@@ -76,7 +76,7 @@ final class RetrySequenceTests: XCTestCase {
7676
let maxIntervalNanos: UInt64 = 10 * 1_000_000_000
7777

7878
let sequence = RetrySequence(
79-
strategy: .exponentialWithJitter(
79+
strategy: .exponential(
8080
retry: 10,
8181
jitterFactor: 0.1,
8282
maxInterval: maxIntervalDuration,
@@ -104,7 +104,7 @@ final class RetrySequenceTests: XCTestCase {
104104

105105
func test_thatRetrySequenceAppliesJitter_whenStrategyIsExponentialWithJitter() {
106106
// given
107-
let strategy = RetryPolicyStrategy.exponentialWithJitter(
107+
let strategy = RetryPolicyStrategy.exponential(
108108
retry: 30,
109109
jitterFactor: 0.5,
110110
maxInterval: nil,
@@ -142,7 +142,7 @@ final class RetrySequenceTests: XCTestCase {
142142
func test_thatRetrySequenceWorksWithoutMaxInterval_whenStrategyIsExponentialWithJitter() {
143143
// given
144144
let sequence = RetrySequence(
145-
strategy: .exponentialWithJitter(
145+
strategy: .exponential(
146146
retry: 5,
147147
jitterFactor: 0.1,
148148
maxInterval: nil,
@@ -171,7 +171,7 @@ final class RetrySequenceTests: XCTestCase {
171171
func test_thatRetrySequenceDoesNotLimitASequence_whenStrategyIsExponentialWithJitterAndMaxIntervalIsNil() {
172172
// given
173173
let sequence = RetrySequence(
174-
strategy: .exponentialWithJitter(
174+
strategy: .exponential(
175175
retry: .retry,
176176
jitterFactor: .jitterFactor,
177177
maxInterval: nil,

0 commit comments

Comments
 (0)