Kotlin Retry Versions Save

A multiplatform higher-order function for retrying operations that may fail.

2.0.1

1 month ago

This release introduces the kotlin-retry-result subproject, leveraging the Result<V, E> type from kotlin-result for code that must be retried but returns an Err instead of throwing an Exception.

See the README section for a full example.

To install the new extension library:

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.michael-bull.kotlin-retry:kotlin-retry:2.0.1")
    implementation("com.michael-bull.kotlin-retry:kotlin-retry-result:2.0.1")
}

2.0.0

2 months ago

Version 2.0.0 represents a major breaking change in the form of an underlying rewrite and support all three tiers of Kotlin/Native.

Multiplatform

The project has been converted to be multiplatform, matching compatibility with kotlinx-coroutines support for all three tiers of Kotlin/Native.

The full list of platform targets can be found in the kotlin-conventions Gradle plugin.

Policy Authoring Changes

The implementation no longer relies on CoroutineContext to persist the state of retry attempts. Instead, the RetryPolicy (now a functional interface) is passed the attempt that just failed. This makes it clear on the callsite what information about the failed attempt is available, instead of being expected to know what fields are in the coroutineContext.retryStatus.

The attempt argument for a RetryPolicy contains:

  • The failure as a generic.
    • In the default case of invoking the retry or runRetrying function, this will be Throwable, however leaves future oppurtunity for a Result-backed retry function that uses an Err instead of a Throwable.
  • A zero-based attempt number.
    • 0 means the invocation of the block has failed and no attempts have been made to retry invoking the block.
    • 1 means the invocation of the block has failed, and one attempt to retry invoking the block also failed - totalling two attempts and one retry.
  • The delay between the failed attempt and the attempt prior.
  • The cumulativeDelay across all attempts.

Before:

public fun binaryExponentialBackoff(min: Long, max: Long): RetryPolicy<*> {
    require(min > 0) { "min must be positive, but was $min" }
    require(max > 0) { "max must be positive, but was $max" }

    return {
        val attempt = coroutineContext.retryStatus.attempt
        val delay = min(max, min saturatedMultiply attempt.binaryExponential())

        RetryAfter(delay)
    }
}

After:

public fun <E> binaryExponentialBackoff(min: Long, max: Long): RetryPolicy<E> {
    require(min > 0) { "min must be positive, but was $min" }
    require(max > 0) { "max must be positive, but was $max" }

    return RetryPolicy { attempt ->
        val delay = min(max, min saturatedMultiply attempt.number.binaryExponential())
        RetryAfter(delay)
    }
}

Function Changes

Various functions have been added, renamed, or their signature otherwise changed to comply with the rewrite.

Renamed

  • maxDelay -> delayAtMost
  • limitAttempts -> stopAtAttempts
  • limitByDelay -> stopAtDelay
  • limitByCumulativeDelay -> stopAtCumulativeDelay
  • retryIf -> continueIf
  • retryUnless -> continueUnless

Added

  • delayAtLeast
  • delayAtMost
  • delayIn
  • stopAtRetries
  • stopIf
  • stopUnless

1.0.9

2 years ago
  • Collapse multiple catch blocks for Graalvm (0c7e6685bbf8ae35563bafc78698350457dac7a7) by @cherrydev
    • Fixes #16

1.0.8

3 years ago
  • Add retryUnless policy (a0b7174ae804ae9114f45c09df1cda36985b017c)
    • Facilitates creating a RetryPolicy that only retries if a given predicate is not satisfied. Analogous to takeUnless in the stdlib.

1.0.7

3 years ago

1.0.6

3 years ago
  • Add compiler contracts (45c7156d04f9256a36306b81caf8a9965d15b7c4)
  • Update Gradle to 6.6.1 (a197636a3ee516b3be029d67e1431306d3ee0815)
  • Handle zero delay returned by full jitter policy (9e7dcf8eafe98b142ef3f0b0ec9f7bb6b7d44416) by @thake
  • Update dependencies (e48517af7f7b2a45e02be49ac72df773db9f8c8a)

1.0.5

4 years ago
  • Add kotlin.code.style=official to gradle.properties (fb8b1100905493a077b6172a559f2bd2a41d0aa8)
  • Update gradle to 6.2-rc-2 (cfd91319318282881da01e901df9ef695fc556b1)
  • Update dependencies (35c30c11f39bf378ca9217da2495c05f38d75273)
  • Replace bintray with maven central (25db7ac3bfd005d3c09c6dc6ded02837bda1b8e7)

1.0.4

4 years ago
  • Update dependencies (31dfa7335d3656f0bab97da63bb8750961b5ae27)
  • Replace travis with github actions (934f05b4cd8c63e1b515873f86589dd17f99870d)

1.0.3

4 years ago
  • Add single LongRange argument factory functions for backoff strategies (548a40d80b7afdc29000ada9035aa25559434f88)

1.0.2

4 years ago
  • Handle merging of zero-delay policies (4e1cf758c0799801398c09142ca53185a2cff537)
    • Fixes #2
  • Update dependencies (58571a28bfe0a6983cb5d248875fab16890e55da)
    • Kotlin Coroutines from 1.3.0 to 1.3.1
    • Gradle from 5.6 to 5.6.2