Latest 1.1.1
Homepage https://github.com/Ybrin/ExponentialBackOff
License MIT
Platforms osx 10.10, ios 8.0, tvos 9.0, requires ARC
Dependencies AsyncSwift
Authors

CI Status
Version
License
Platform

Description

This framework implements the ExponentialBackOff algorithm which reruns given code after an amount of time which you can change until it succeeds or the Timeout exceeds. This can be usefull for Networking in your application.

If you want to refresh a list by calling an API Request, you may want to check the Internet availability with Reachability and if there is no connection available you would recheck it after some time manually.
And this is where this API comes into play. It rereuns your code automatically on a exponential basis.
The time to wait until the next attempt is calculated as follows:

next_interval = retry_interval * (random value in range [1 - randomization_factor, 1 + randomization_factor])

and retry_interval is calculated like that:

retry_interval = last_retry_interval * multiplier

If this is the first re-attempt, last_retry_interval will be set to initial_retry_interval

The default values are as follows:

public static let DEFAULT_INITIAL_INTERVAL_MILLIS: Int = 500 // 0.5 seconds

public static let DEFAULT_MAX_ELAPSED_TIME_MILLIS: Int = 900000 // 15 minutes

public static let DEFAULT_MAX_INTERVAL_MILLIS: Int = 60000 // Intervall won't increase any more - 5 minutes

public static let DEFAULT_MULTIPLIER: Double = 1.5 // 1.5

public static let DEFAULT_RANDOMIZATION_FACTOR: Double = 0.5 // 0.5 or 50%

You can change any of these values to whatever you want but they are also the default values at Google’s Java API library which should be used to request GCM tokens for example.

Installation

ExponentialBackOff is available through CocoaPods. To install
it, simply add the following line to your Podfile:

pod "ExponentialBackOff"

Usage

Basic usage is very straightforward. The following code shows a simple example on how to use the framework.

let builder = ExponentialBackOffInstance.Builder()
let exponentialBackOff = ExponentialBackOffInstance(builder: builder)

ExponentialBackOff.sharedInstance.runGeneralBackOff(exponentialBackOff) {
    (lastIntervallMillis, elapsedTimeMillis, completion) in

    print("Last interval: (lastIntervallMillis)")
    print("Elapsed time overall: (elapsedTimeMillis)")

    let randomNumber = arc4random_uniform(100)

    if randomNumber == 28 {
        print("Success! Terminating the back-off instance.")
        completion(success: true)
    } else {
        print("Failed, retrying after some time.")
        completion(success: false)
    }

     }

Actually thats it. Now build the project and lean back. If you are lucky, it will eventually print Success. If not it will try again and again with bigger intervals between the attempts each time until it reaches the Timeout (maxElapsedTimeMillis).

Note: Your code will be executed on a background Thread so if you must run it on the main Thread you should wrap it either with AsyncSwift like that: Async.main {} or like that: dispatch_async(dispatch_get_main_queue()) {}.


If you want to change some default values you can manipulate your Builder‘s members:

let builder = ExponentialBackOffInstance.Builder()
builder.initialIntervalMillis = 2000
builder.maxElapsedTimeMillis = 100000
builder.maxIntervalMillis = 10000
builder.randomizationFactor = 0.2
builder.multiplier = 2.0

let exponentialBackOff = ExponentialBackOffInstance(builder: builder)

ExponentialBackOff.sharedInstance.runGeneralBackOff(exponentialBackOff) {
    (lastIntervallMillis, elapsedTimeMillis, completion) in

    // Last interval millis is never greater than maxIntervalMillis
    print("Last interval: (lastIntervallMillis)")

    // If the elapsedTime exceeds maxElapsedTimeMillis the ExponentialBackOffInstance exits with
    // BackOffState.Failed as the currentState
    print("Elapsed time overall: (elapsedTimeMillis)")

    let randomNumber = arc4random_uniform(100)

    if randomNumber == 97 {
        print("Success! Terminating the back-off instance.")
        completion(success: true)
    } else {
        print("Failed, retrying after some time.")
        completion(success: false)
    }

}

You can read some values from your ExponentialBackOffInstance:

let exponentialBackOff = ExponentialBackOffInstance(builder: builder)
.
.
.

if exponentialBackOff.currentState == .Failed {
    exponentialBackOff.reset() // Restarts the back-off with the same code.
}

if exponentialBackOff.attempts >= 100 {
    exponentialBackOff.stopExecution() // Stops the execution and sets currentState to BackOffState.Stopped
}

More examples soon…

Example Project

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

  • iOS 8.0+ / Mac OS X 10.9+
  • Xcode 7.2+
  • AsyncSwift 1.7+ (Cocoapods will install all dependencies automatically)

Author

Ybrin, [email protected]

License

ExponentialBackOff is available under the MIT license. See the LICENSE file for more info.

Latest podspec

{
    "name": "ExponentialBackOff",
    "version": "1.1.1",
    "summary": "A framework which implements the ExponentialBackOff algorithm which is usefull for Networking.",
    "description": "This framework implements the ExponentialBackOff algorithm which you can use for Networking or other tasks which should be retried after some time without worrying about how long you have to wait for the next attempt.nGoogle mentioned this algorithm to be used to request a GCM token. In Java they implemented this in their java api repository but for iOS and OSX developers this is the right framework.nI tried to put more features into this pod than simple a lame algorithm without much more.nFor example you just have to pass your code as a closure or by implementing a Protocol and passing the class to one of the methods. You don't have to worry about waiting the right amount of time or recalling your code, the Handler makes this automatically.nYou also have the option to implement your own algorithm without worrying about how to handle the automatic reattempts.",
    "homepage": "https://github.com/Ybrin/ExponentialBackOff",
    "license": "MIT",
    "authors": {
        "Ybrin": "[email protected]"
    },
    "source": {
        "git": "https://github.com/Ybrin/ExponentialBackOff.git",
        "tag": "1.1.1"
    },
    "platforms": {
        "osx": "10.10",
        "ios": "8.0",
        "tvos": "9.0"
    },
    "requires_arc": true,
    "source_files": "ExponentialBackOff/ExponentialBackOff/**/*",
    "dependencies": {
        "AsyncSwift": [
            "~> 2.0"
        ]
    },
    "pushed_with_swift_version": "3.0"
}

Pin It on Pinterest

Share This