Skip to content

Commit 9c52525

Browse files
committed
hm
1 parent fb42e6e commit 9c52525

File tree

1 file changed

+26
-7
lines changed

1 file changed

+26
-7
lines changed

Sources/SwiftAPIClient/Modifiers/RetryModifier.swift

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ public struct RetryRequestCondition {
297297
if case let .success(response) = response {
298298
return codes.contains(response.status)
299299
}
300-
return true
300+
return false
301301
}
302302
}
303303
}
@@ -339,7 +339,9 @@ private struct retryMiddleware: HTTPClientMiddleware {
339339
let interval = configs.retryInterval
340340
let backoffPolicy = configs.retryBackoffPolicy
341341
if let hash = backoffPolicy.scopeHash(request) {
342-
await waitForSynchronizedAccess(id: hash, of: Void.self)
342+
if let interval = await waitForSynchronizedAccess(id: hash, of: UInt64.self) {
343+
try await Task.sleep(nanoseconds: jitterNs(interval))
344+
}
343345
}
344346
var count = 0
345347
var resp: HTTPResponse?
@@ -350,7 +352,7 @@ private struct retryMiddleware: HTTPClientMiddleware {
350352
return false
351353
}
352354
if let limit {
353-
return count <= limit
355+
return count < limit
354356
}
355357
return true
356358
}
@@ -360,8 +362,9 @@ private struct retryMiddleware: HTTPClientMiddleware {
360362
let interval = UInt64(max(retryAfterHeader, interval(count - 1)) * 1_000_000_000)
361363
if interval > 0 {
362364
if let resp, let hash = backoffPolicy.scopeHash(request), backoffPolicy.isGlobalBackoff(request, resp) {
363-
try await withThrowingSynchronizedAccess(id: hash) {
365+
_ = try await withThrowingSynchronizedAccess(id: hash) {
364366
try await Task.sleep(nanoseconds: interval)
367+
return interval
365368
}
366369
} else {
367370
try await Task.sleep(nanoseconds: interval)
@@ -377,9 +380,11 @@ private struct retryMiddleware: HTTPClientMiddleware {
377380
do {
378381
let (data, response) = try await retry()
379382
resp = response
380-
retryAfterHeader = response.headerFields[.retryAfter].flatMap {
381-
decodeRetryAfterHeader($0, formatter: configs.retryAfterHeaderDateFormatter)
382-
} ?? 0
383+
if [429, 503].contains(response.status.code) {
384+
retryAfterHeader = response.headerFields[.retryAfter].flatMap {
385+
decodeRetryAfterHeader($0, formatter: configs.retryAfterHeaderDateFormatter)
386+
} ?? 0
387+
}
383388
if !needRetry(.success(response)) {
384389
return (data, response)
385390
}
@@ -393,6 +398,20 @@ private struct retryMiddleware: HTTPClientMiddleware {
393398
}
394399
}
395400

401+
@inline(__always)
402+
private func jitterNs(
403+
_ base: UInt64,
404+
fraction: ClosedRange<Double> = 0.1...0.2,
405+
minNs: UInt64 = 5_000_000, // 5 ms
406+
maxNs: UInt64 = 1_000_000_000
407+
) // 1 s
408+
-> UInt64 {
409+
guard base > 0 else { return 0 }
410+
let p = Double.random(in: fraction)
411+
let raw = UInt64(Double(base) * p)
412+
return min(max(raw, minNs), maxNs)
413+
}
414+
396415
private func decodeRetryAfterHeader(_ value: String, formatter: DateFormatter) -> TimeInterval? {
397416
// seconds
398417
if let seconds = TimeInterval(value) {

0 commit comments

Comments
 (0)