import Combine import Foundation /// Attempt and retry a task that fails with resume data up to `maximumRetryCount` times func attemptResumableTask( maximumRetryCount: Int = 3, delayBeforeRetry: TimeInterval = 2, _ body: @escaping (Data?) -> AnyPublisher ) -> AnyPublisher { var attempts = 0 func attempt(with resumeData: Data? = nil) -> AnyPublisher { attempts += 1 return body(resumeData) .catch { error -> AnyPublisher in guard attempts < maximumRetryCount, let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data else { return Fail(error: error).eraseToAnyPublisher() } return attempt(with: resumeData) .delay(for: .seconds(delayBeforeRetry), scheduler: DispatchQueue.main) .eraseToAnyPublisher() } .eraseToAnyPublisher() } return attempt() } ///// Attempt and retry a task up to `maximumRetryCount` times //func attemptRetryableTask( // maximumRetryCount: Int = 3, // delayBeforeRetry: DispatchTimeInterval = .seconds(2), // _ body: @escaping () -> AnyPublisher //) -> AnyPublisher { // var attempts = 0 // func attempt() -> Promise { // attempts += 1 // return body().recover { error -> Promise in // guard attempts < maximumRetryCount else { throw error } // return after(delayBeforeRetry).then(on: nil) { attempt() } // } // } // return attempt() //}