Created
January 25, 2022 00:40
-
-
Save chrisvasselli/1f20d8b358582523953538e36d88daf7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension Error { | |
var code: Int { return (self as NSError).code } | |
var domain: String { return (self as NSError).domain } | |
var userInfo: [String:Any] { return (self as NSError).userInfo } | |
func timeAfterWhichToRetry(retryCount: Int) -> TimeInterval? { | |
// CloudKit suggests us retry too often, so slow us down as we retry a lot, up to 5 minutes | |
if let suggestedTimeout = suggestedTimeAfterWhichToRetry { | |
if suggestedTimeAfterWhichToRetry == 0 { | |
return 0 | |
} | |
else { | |
return max(min(5.0 * 60.0, TimeInterval(retryCount) * 10.0), suggestedTimeout) | |
} | |
} | |
else { | |
return nil | |
} | |
} | |
private var suggestedTimeAfterWhichToRetry: TimeInterval? { | |
if domain == CKErrorDomain && code == CKError.quotaExceeded.rawValue { | |
return nil | |
} | |
// If we are rate limited because we previously failed because the user ran out of iCloud space, we want to immediately stop and show them that error | |
if domain == CKErrorDomain, code == CKError.requestRateLimited.rawValue, let errorDescription = userInfo["CKErrorDescription"] as? String, errorDescription.contains("Quota exceeded") { | |
return nil | |
} | |
if let retryAfter = userInfo[CKErrorRetryAfterKey] as? TimeInterval { | |
return retryAfter | |
} | |
if domain == CKErrorDomain && code == CKError.partialFailure.rawValue, | |
let ckError = self as? CKError, let suberrors = ckError.partialErrorsByItemID?.values, | |
let timeout = suberrors.compactMap({ $0.suggestedTimeAfterWhichToRetry }).first { | |
return timeout | |
} | |
switch self { | |
case URLError.timedOut, URLError.notConnectedToInternet, URLError.secureConnectionFailed: // Transient network issues that seems like they might resolve quickly | |
return 10 | |
case CKError.zoneBusy, CKError.requestRateLimited: // Expect this to have a retryAfter, but sometimes it doesn't | |
return 30 | |
default: | |
return nil | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment