Skip to content

Instantly share code, notes, and snippets.

@chrisvasselli
Created January 25, 2022 00:40
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save chrisvasselli/1f20d8b358582523953538e36d88daf7 to your computer and use it in GitHub Desktop.
Save chrisvasselli/1f20d8b358582523953538e36d88daf7 to your computer and use it in GitHub Desktop.
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