Releases: michaelbull/kotlin-retry
2.0.1
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
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
orrunRetrying
function, this will beThrowable
, however leaves future oppurtunity for aResult
-backedretry
function that uses anErr
instead of aThrowable
.
- In the default case of invoking the
- A zero-based attempt number.
0
means the invocation of theblock
has failed and no attempts have been made to retry invoking theblock
.1
means the invocation of theblock
has failed, and one attempt to retry invoking theblock
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
- Collapse multiple catch blocks for Graalvm (0c7e668) by @cherrydev
- Fixes #16
1.0.8
- Add retryUnless policy (a0b7174)
- Facilitates creating a
RetryPolicy
that only retries if a given predicate is not satisfied. Analogous totakeUnless
in the stdlib.
- Facilitates creating a