Skip to content

Commit b985ed0

Browse files
authored
NNNN-retry-backoff.md aktualisieren (#6)
1 parent 18331e2 commit b985ed0

File tree

1 file changed

+27
-26
lines changed

1 file changed

+27
-26
lines changed

Evolution/NNNN-retry-backoff.md

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ extension BackoffStrategy {
6868
public func maximum(_ maximum: Duration) -> some BackoffStrategy<Duration>
6969
}
7070
@available(iOS 18.0, macCatalyst 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *)
71-
extension BackoffStrategy {
71+
extension BackoffStrategy where Duration == Swift.Duration {
7272
public func fullJitter<RNG: RandomNumberGenerator>(using generator: RNG = SystemRandomNumberGenerator()) -> some BackoffStrategy<Duration>
7373
public func equalJitter<RNG: RandomNumberGenerator>(using generator: RNG = SystemRandomNumberGenerator()) -> some BackoffStrategy<Duration>
7474
}
@@ -96,21 +96,21 @@ The retry algorithm follows this sequence:
9696
1. Execute the operation
9797
2. If successful, return the result
9898
3. If failed and this was not the final attempt:
99-
- Call the `strategy` closure with the error
100-
- If strategy returns `.stop`, rethrow the error immediately
101-
- If strategy returns `.backoff`, suspend for the given duration
102-
- Return to step 1
99+
- Call the `strategy` closure with the error
100+
- If the strategy returns `.stop`, rethrow the error immediately
101+
- If the strategy returns `.backoff`, suspend for the given duration
102+
- Return to step 1
103103
4. If failed on the final attempt, rethrow the error without consulting the strategy
104104

105-
Given this sequence, there is a total of four termination conditions (when retrying will be stopped):
105+
Given this sequence, there are four termination conditions (when retrying will be stopped):
106106
- The operation completes without throwing an error
107107
- The operation has been attempted `maxAttempts` times
108108
- The strategy closure returns `.stop`
109-
- The given clock throws
109+
- The clock throws
110110

111111
#### Cancellation
112112

113-
`retry` does not introduce special cancellation handling. If your code cooperatively cancels by throwing, ensure your strategy returns `.stop` for that error. Otherwise, retries will continue unless the given clock throws on cancellation (which, at the time of writing, both `ContinuousClock` and `SuspendingClock` do).
113+
`retry` does not introduce special cancellation handling. If your code cooperatively cancels by throwing, ensure your strategy returns `.stop` for that error. Otherwise, retries continue unless the clock throws on cancellation (which, at the time of writing, both `ContinuousClock` and `SuspendingClock` do).
114114

115115
### Backoff
116116

@@ -126,20 +126,20 @@ var backoff = Backoff
126126

127127
Adopters may choose to create their own strategies. There is no requirement to conform to `BackoffStrategy`, since retry and backoff are decoupled; however, to use the provided modifiers (`minimum`, `maximum`, `jitter`), a strategy must conform.
128128

129-
Each call to `nextDuration()` returns the delay for the next retry attempt. Strategies are naturally stateful. For instance they may track the number of invocations or the previously returned duration to calculate the next delay.
129+
Each call to `nextDuration()` returns the delay for the next retry attempt. Strategies are naturally stateful. For instance, they may track the number of invocations or the previously returned duration to calculate the next delay.
130130

131131
#### Standard backoff
132132

133133
As previously mentioned this proposal introduces several common backoff strategies which include:
134134

135-
- **Constant**: $`f(n) = constant`$
136-
- **Linear**: $`f(n) = initial + increment * n`$
137-
- **Exponential**: $`f(n) = initial * factor ^ n`$
138-
- **Decorrelated Jitter**: $`f(n) = random(base, f(n - 1) * factor)`$ where $`f(0) = base`$
139-
- **Minimum**: $`f(n) = max(minimum, g(n))`$ where `g(n)` is the base strategy
140-
- **Maximum**: $`f(n) = min(maximum, g(n))`$ where `g(n)` is the base strategy
141-
- **Full Jitter**: $`f(n) = random(0, g(n))`$ where `g(n)` is the base strategy
142-
- **Equal Jitter**: $`f(n) = random(g(n) / 2, g(n))`$ where `g(n)` is the base strategy
135+
- **Constant**: $f(n) = constant$
136+
- **Linear**: $f(n) = initial + increment * n$
137+
- **Exponential**: $f(n) = initial * factor ^ n$
138+
- **Decorrelated Jitter**: $f(n) = random(base, f(n - 1) * factor)$ where $f(0) = base$
139+
- **Minimum**: $f(n) = max(minimum, g(n))$ where $g(n)$ is the base strategy
140+
- **Maximum**: $f(n) = min(maximum, g(n))$ where $g(n)$ is the base strategy
141+
- **Full Jitter**: $f(n) = random(0, g(n))$ where $g(n)$ is the base strategy
142+
- **Equal Jitter**: $f(n) = random(g(n) / 2, g(n))$ where $g(n)$ is the base strategy
143143

144144
### Case studies
145145

@@ -150,7 +150,7 @@ The most common use cases encountered for recovering from transient failures are
150150
Both of these use cases can be implemented using the proposed algorithm, respectively:
151151

152152
```swift
153-
let rng = SystemRandomNumberGenerator() // or a seeded rng for unit tests
153+
let rng = SystemRandomNumberGenerator() // or a seeded RNG for unit tests
154154
var backoff = Backoff
155155
.exponential(factor: 2, initial: .milliseconds(100))
156156
.maximum(.seconds(10))
@@ -169,9 +169,10 @@ let response = try await retry(maxAttempts: 5) {
169169
if
170170
let response = response as? HTTPURLResponse,
171171
response.statusCode == 429,
172-
let retryAfter = response.value(forHTTPHeaderField: "Retry-After")
172+
let retryAfter = response.value(forHTTPHeaderField: "Retry-After"),
173+
let seconds = Double(retryAfter)
173174
{
174-
throw TooManyRequestsError(retryAfter: Double(retryAfter)!)
175+
throw TooManyRequestsError(retryAfter: seconds)
175176
}
176177
return (data, response)
177178
} strategy: { error in
@@ -182,18 +183,18 @@ let response = try await retry(maxAttempts: 5) {
182183
}
183184
}
184185
```
185-
(For demonstration purposes only, a network server is used as remote system)
186+
(For demonstration purposes only, a network server is used as the remote system.)
186187

187188
## Effect on API resilience
188189

189-
This proposal introduces purely additive API with no impact on existing functionality or API resilience.
190+
This proposal introduces a purely additive API with no impact on existing functionality or API resilience.
190191

191192
## Future directions
192193

193194
The jitter variants introduced by this proposal support custom `RandomNumberGenerator` by **copying** it in order to perform the necessary mutations.
194-
This is not optimal and does not match the standard libraries signatures of e.g. `shuffle()` or `randomElement()` which take an **`inout`** random number generator.
195-
Due to the composability of backoff algorithms proposed, this is not possible to adopt in current Swift.
196-
If Swift at one point gains the capability to "store" `inout` variables the jitter variants should try to adopt this by introducing new `inout` overloads and deprecating the copying overloads.
195+
This is not optimal and does not match the standard library's signatures of e.g. `shuffle()` or `randomElement()` which take an **`inout`** random number generator.
196+
Due to the composability of backoff algorithms proposed here, this is not possible to adopt in current Swift.
197+
If Swift gains the capability to "store" `inout` variables, the jitter variants should adopt this by adding new `inout` overloads and deprecating the copying overloads.
197198

198199
## Alternatives considered
199200

@@ -202,4 +203,4 @@ why you chose this approach instead.
202203

203204
## Acknowledgments
204205

205-
Thanks to [Philippe Hausler](https://github.com/phausler), [Franz Busch](https://github.com/FranzBusch) and [Honza Dvorsky](https://github.com/czechboy0) for their thoughtful feedback and suggestions that helped refine the API design and improve its clarity and usability.
206+
Thanks to [Philippe Hausler](https://github.com/phausler), [Franz Busch](https://github.com/FranzBusch) and [Honza Dvorsky](https://github.com/czechboy0) for their thoughtful feedback and suggestions that helped refine the API design and improve its clarity and usability.

0 commit comments

Comments
 (0)