Retry Logic and Background URLSession
Implementing exponential backoff and continuing downloads in the background.
Why Retry?
Transient failures (timeouts, 503 Service Unavailable) are recoverable. Retry logic improves resilience without user intervention.
func fetch(retries: Int = 3) async throws -> Data {
for attempt in 0..<retries {
do {
return try await URLSession.shared.data(from: url).0
} catch {
if attempt == retries - 1 { throw error }
}
}
fatalError("unreachable")
}Exponential Backoff
Wait increasingly longer between retries to avoid overwhelming a struggling server: 1s, 2s, 4s.
for attempt in 0..<maxRetries {
do { return try await fetch() } catch {
if attempt < maxRetries - 1 {
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(attempt))) * 1_000_000_000)
} else { throw error }
}
}All lessons in this course
- URLSession data(from:) with async/await
- Codable: Encoding and Decoding JSON
- Error Handling and HTTP Status Codes
- Retry Logic and Background URLSession