Skip to content

Instantly share code, notes, and snippets.

@wotjd
Forked from iamchiwon/retryInterval.swift
Last active May 24, 2020 13:50
Show Gist options
  • Save wotjd/236cee3662f052eba5e66b8adca3cc04 to your computer and use it in GitHub Desktop.
Save wotjd/236cee3662f052eba5e66b8adca3cc04 to your computer and use it in GitHub Desktop.
RxSwift retry interval with condition
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