Coder Social home page Coder Social logo

michaelbull / kotlin-retry Goto Github PK

View Code? Open in Web Editor NEW
323.0 4.0 9.0 266 KB

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

License: ISC License

Kotlin 100.00%
kotlin retry io high-order-function functional-programming backoff jitter kotlin-multiplatform

kotlin-retry's People

Contributors

cherrydev avatar gnefedev avatar jfjallstrom avatar michaelbull avatar nicoder avatar thake avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

kotlin-retry's Issues

There is no filter function to retry only specific exceptions

In my project, I wrote

`import com.github.michaelbull.retry.ContinueRetrying
import com.github.michaelbull.retry.StopRetrying
import com.github.michaelbull.retry.policy.RetryPolicy

fun filter(test: (Throwable) -> Boolean): RetryPolicy = {
if (test(this.reason)) {
ContinueRetrying
} else {
StopRetrying
}
}`

retryResult signature makes it easy to use wrong context

It seems that issue #4 was closed, but I have also inadvertently run into this situation today with similar code:

    withTimeout(1000) {
        retryResult {
            // This crashes because coroutineContext is obtained from the withTimeout scope
//            println("My retryStatus is ${coroutineContext.retryStatus}")

            // This is okay (naming conflict with coroutineContext)
            println("My retryStatus is ${kotlin.coroutines.coroutineContext.retryStatus}")

            // This is also okay
            coroutineScope {
                println("My retryStatus is ${coroutineContext.retryStatus}")
            }

            Ok(Unit)
        }
    }

I was able to workaround this issue fairly easily, but it is easy to shoot yourself in the foot. I understand it would be a breaking api change to update the type signature of ResultProducer. Is there any other reason why you wouldn't want to provide the proper scope to the retryResult block?

Call retry with a non-Throwable RetryPolicy

It would be extremely useful for a retry method to exist that uses a RetryPolicy that does not require the use of a Throwable.

An example use-case of this might be when an API call is made, no error is thrown but the HTTP code is one that is unexpected

For example this code lifted from a side project of mine:

private val retryServerCallPolicy: RetryPolicy<NetworkResponse<*, *>> = {
        when (reason) {
            is NetworkResponse.ApiError -> when (reason.code) {
                in 500..599 -> ContinueRetrying
                else -> StopRetrying
            }
            else -> StopRetrying
        }
    }

Which ideally could be used in this way:

retry(retryServerCallPolicy + limitAttempts(3)) {
    myApiCallMethod()
}

I'd love to know what your thoughts are on this.

New version with retryIf

Super short request: could you release a new version with 201a368350020b5d54cc112d0a9dd9024df467fb included in it?

Making it possible to log retry attemps

First of all, thanks for this lightweight library!

I tried emitting a warning log message whenever a retry attempt fails. Unfortunately, I wasn't able to log out the current attempt number. Is there a way to do this?

One possibility would be to add a new field "failedAttempt" to RetryFailure. Then one could log out the attempt number in the RetryPolicy.

RetryPolicy creation is order dependent

Thanks for this lib! I've had one minor hiccup whilst utilising in my current code, as demonstrated by this simple unit test:

package somepackage

import com.github.michaelbull.retry.ContinueRetrying
import com.github.michaelbull.retry.StopRetrying
import com.github.michaelbull.retry.policy.RetryPolicy
import com.github.michaelbull.retry.policy.fullJitterBackoff
import com.github.michaelbull.retry.policy.limitAttempts
import com.github.michaelbull.retry.policy.plus
import com.github.michaelbull.retry.retry
import kotlinx.coroutines.runBlocking
import org.junit.Test

class RetryTest {
    private val retryFailures: RetryPolicy<Throwable> = {
        when (reason) {
            is RuntimeException -> ContinueRetrying

            else -> StopRetrying
        }
    }

    @Test
    fun doesnotwork() = runBlocking {
        // this fails because the RetryPolicy is considered incorrect...delayMillis equals 0 after first '+'         
        retry(retryFailures + limitAttempts(5) + fullJitterBackoff(100, 1000)) {
            doSomethingWrong()
        }
    }

    @Test
    fun works() = runBlocking {
        retry(fullJitterBackoff(100, 1000) + retryFailures + limitAttempts(5)) {
            doSomethingWrong()
        }
    }


    private fun doSomethingWrong() {
        throw RuntimeException("Gotcha")
    }
}

It seems that the plus operator is prematurely enforcing the validation of the final Policy before all elements might have been added in. Perhaps the 'delayMillis' validation can be done after this line in Retry.kt?

                val instruction = RetryFailure(t).policy()

Publishing library to Jcenter

Hello,
Thanks for very cool library!
I'd like to include it to my work project, but my org. policies doesn't allow me to use bintray repositories.
Could you please add you library to Jcenter?
I'm also ready to help if you need any.
Thanks!

Is throwing from a RetryPolicy supported?

I'm trying to adapt some existing inflexible retry code to use your library.

One thing we do is that in some cases our retry function throws a different exception than the wrapped code. eg, we say "retry if the exception is T; if we have given up after too many Ts, throw T1, but if an unexpected exception happened just throw it directly".

We can implement this by having a RetryPolicy that actually throws T1 instead of returning StopRetrying, and it appears to work in the current implementation. Is this something we can rely on?

Retry with `Result`?

Any plans to bring back retryResult?

It looks like it was dropped in db1c515 ("Rewrite to remove dependency on CoroutineContext").

Maybe it would make sense (for library consumers that don't use Result) to provide retryResult via an additional Maven artifact?

Thank you!

Kotlin multiplatform support?

I am using this library with ktor on JVM and really liking it. Thanks for all the work done on this library. Are there any plans to support other kotlin targets, especially web and native ?

Filter retry by multiple exception types

This makes it more usable

fun onException(vararg types: KClass<out Throwable>): RetryPolicy<Throwable> {
    return {
        if (types.any { it.isInstance(reason) }) ContinueRetrying else StopRetrying
    }
}

In some cases there is not a common base class for all exceptions that should trigger retry.

Full jitter backoff policy may lead to IllegalArgumentException

Thanks for your work on this nice library!

I found out that the following exception may be thrown if the backoff policy full jitter is used:

java.lang.IllegalArgumentException: delayMillis must be positive: 0
	at com.github.michaelbull.retry.policy.BackoffKt$fullJitterBackoff$3.invokeSuspend(Backoff.kt:120)
	at com.github.michaelbull.retry.policy.BackoffKt$fullJitterBackoff$3.invoke(Backoff.kt)
	at com.github.michaelbull.retry.policy.BackoffTest$simulate$2.invokeSuspend(BackoffTest.kt:43)
	at com.github.michaelbull.retry.policy.BackoffTest$simulate$2.invoke(BackoffTest.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:160)
	at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)

This is caused by the use of the random function without a lower bound. Thus the random delay can be 0. If you don't mind, I'll provide a pull request.

Graalvm incompatibility (easily fixed)

So, there's some sort of issue with Graalvm where it complains about "merging incompatible frames". It results in an error as shown in oracle/graal#3342 but manifests when rethrowing exceptions. Thankfully, the fix is really simple and I will open up a pull request.

Expose coroutine scope in retry

It would be helpful for logging to be able to access the coroutine scope inside of the retry function. For example being able to see:

    retry(limitAttempts(5)) {
        println(coroutineContext.retryStatus.attempt)
    }

thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.