Skip to content

Instantly share code, notes, and snippets.

@kean
Last active November 2, 2024 15:47
Show Gist options
  • Save kean/e2bc38106d19c249c04162714e7be321 to your computer and use it in GitHub Desktop.
Save kean/e2bc38106d19c249c04162714e7be321 to your computer and use it in GitHub Desktop.

Revisions

  1. kean revised this gist Jan 10, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion AutoRetry.swift
    Original file line number Diff line number Diff line change
    @@ -21,7 +21,7 @@ extension ObservableType {
    shouldRetry: @escaping (Error) -> Bool = { _ in true }) -> Observable<E> {
    return retryWhen { (errors: Observable<Error>) in
    return errors.enumerated().flatMap { attempt, error -> Observable<Void> in
    guard shouldRetry(error), maxAttemptCount > attempt + 1 else {
    guard maxAttemptCount > attempt + 1, shouldRetry(error) else {
    return .error(error)
    }

  2. kean revised this gist Dec 25, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion AutoRetry.swift
    Original file line number Diff line number Diff line change
    @@ -50,7 +50,7 @@ extension DelayOptions {
    case .constant(let time): return time
    case .exponential(let initial, let multiplier, let maxDelay):
    // if it's first attempt, simply use initial delay, otherwise calculate delay
    let delay = attempt == 1 ? initial : initial * pow(1 + multiplier, Double(attempt - 1))
    let delay = attempt == 1 ? initial : initial * pow(multiplier, Double(attempt - 1))
    return min(maxDelay, delay)
    case .custom(let closure): return closure(attempt)
    }
  3. kean renamed this gist Dec 25, 2017. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. kean revised this gist Dec 25, 2017. 1 changed file with 38 additions and 0 deletions.
    38 changes: 38 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    // The MIT License (MIT)
    //
    // Copyright (c) 2017 Alexander Grebenyuk (github.com/kean).

    import Foundation
    import Alamofire
    import RxSwift
    import RxCocoa


    final class Reachability {
    static var shared: Reachability {
    return AppContainer.shared.reachability
    }

    /// Monitors general network reachability.
    let reachability = NetworkReachabilityManager()

    var didBecomeReachable: Signal<Void> { return _didBecomeReachable.asSignal() }
    private let _didBecomeReachable = PublishRelay<Void>()

    init() {
    self.isReachable = _isReachable.asDriver()

    if let reachability = self.reachability {
    reachability.listener = { [weak self] in
    self?.update($0)
    }
    reachability.startListening()
    }
    }

    private func update(_ status: NetworkReachabilityManager.NetworkReachabilityStatus) {
    if case .reachable = status {
    _didBecomeReachable.accept(())
    }
    }
    }
  5. kean created this gist Dec 25, 2017.
    58 changes: 58 additions & 0 deletions AutoRetry.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    // The MIT License (MIT)
    //
    // Copyright (c) 2017 Alexander Grebenyuk (github.com/kean).

    import Foundation
    import RxSwift
    import RxCocoa


    extension ObservableType {
    /// Retries the source observable sequence on error using a provided retry
    /// strategy.
    /// - parameter maxAttemptCount: Maximum number of times to repeat the
    /// sequence. `Int.max` by default.
    /// - parameter didBecomeReachable: Trigger which is fired when network
    /// connection becomes reachable.
    /// - parameter shouldRetry: Always retruns `true` by default.
    func retry(_ maxAttemptCount: Int = Int.max,
    delay: DelayOptions,
    didBecomeReachable: Signal<Void> = Reachability.shared.didBecomeReachable,
    shouldRetry: @escaping (Error) -> Bool = { _ in true }) -> Observable<E> {
    return retryWhen { (errors: Observable<Error>) in
    return errors.enumerated().flatMap { attempt, error -> Observable<Void> in
    guard shouldRetry(error), maxAttemptCount > attempt + 1 else {
    return .error(error)
    }

    let timer = Observable<Int>.timer(
    RxTimeInterval(delay.make(attempt + 1)),
    scheduler: MainScheduler.instance
    ).map { _ in () } // cast to Observable<Void>

    return Observable.merge(timer, didBecomeReachable.asObservable())
    }
    }
    }
    }

    enum DelayOptions {
    case immediate()
    case constant(time: Double)
    case exponential(initial: Double, multiplier: Double, maxDelay: Double)
    case custom(closure: (Int) -> Double)
    }

    extension DelayOptions {
    func make(_ attempt: Int) -> Double {
    switch self {
    case .immediate: return 0.0
    case .constant(let time): return time
    case .exponential(let initial, let multiplier, let maxDelay):
    // if it's first attempt, simply use initial delay, otherwise calculate delay
    let delay = attempt == 1 ? initial : initial * pow(1 + multiplier, Double(attempt - 1))
    return min(maxDelay, delay)
    case .custom(let closure): return closure(attempt)
    }
    }
    }