-
-
Save wotjd/236cee3662f052eba5e66b8adca3cc04 to your computer and use it in GitHub Desktop.
RxSwift retry interval with condition
This file contains hidden or 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
import RxSwift | |
// concept from RxSwiftExt | |
public enum RetryInterval { | |
case immediate(count: Int) | |
case delayed(count: Int, interval: DispatchTimeInterval) | |
case exponential(count: Int, initial: DispatchTimeInterval, multiplier: Int) | |
case custom(count: Int, delayCalculator: (Int) -> DispatchTimeInterval) | |
var intervals: [DispatchTimeInterval] { | |
switch self { | |
case let .immediate(count): | |
return .init(repeating: .never, count: count) | |
case let .delayed(count, interval): | |
return .init(repeating: interval, count: count) | |
case let .exponential(count, initial, multiplier): | |
let number: Int? | |
let generator: (Int) -> DispatchTimeInterval | |
switch initial { | |
case let .seconds(seconds) where seconds > 0: | |
number = seconds | |
generator = DispatchTimeInterval.seconds | |
case let .milliseconds(milliseconds) where milliseconds > 0: | |
number = milliseconds | |
generator = DispatchTimeInterval.milliseconds | |
case let .microseconds(microseconds) where microseconds > 0: | |
number = microseconds | |
generator = DispatchTimeInterval.microseconds | |
case let .nanoseconds(nanoseconds) where nanoseconds > 0: | |
number = nanoseconds | |
generator = DispatchTimeInterval.nanoseconds | |
default: | |
number = nil | |
generator = { _ in .never } | |
} | |
return number | |
.map { number -> [DispatchTimeInterval] in | |
self.createExponentialArray(count: count, initial: number, multiplier: multiplier) | |
.map(generator) | |
} | |
?? .init(repeating: .never, count: count) | |
case let .custom(count, delayCalculator): | |
return Array(stride(from: 1, through: count, by: 1)) | |
.map(delayCalculator) | |
} | |
} | |
private func createExponentialArray(count: Int, initial: Int, multiplier: Int) -> [Int] { | |
var array = [Int](repeating: initial, count: count) | |
for (index, value) in array.enumerated() { | |
array[index] = value * Int(pow(Double(multiplier), Double(index))) | |
} | |
return array | |
} | |
} | |
extension ObservableType { | |
// default behavior: retry for all errors | |
public func retry(interval: RetryInterval, scheduler: RxSwift.SchedulerType, when condition: @escaping (Error) -> Bool = { _ in true }) -> Observable<Self.Element> { | |
self | |
.retryWhen { error -> Observable<Int> in | |
error | |
.flatMap({ condition($0) ? Observable.just(()) : .error($0) }) | |
.zip(with: Observable.from(interval.intervals), resultSelector: { $1 }) | |
.flatMap({ Observable.timer($0, scheduler: scheduler) }) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment