Skip to content

[question] how to use failsafe with kotlin #375

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ntthaibk opened this issue Jan 11, 2024 · 3 comments
Open

[question] how to use failsafe with kotlin #375

ntthaibk opened this issue Jan 11, 2024 · 3 comments

Comments

@ntthaibk
Copy link

Hi folks, so I'm been using failsafe for java for quite a long time, now I'm moving to new project and decided to adopt it. But run into a problem

When I do Failsafe.with(retryPolicy).get {
...
}

kotlin compiler always say that Kotlin: Overload resolution ambiguity
Overload resolution ambiguity. All these functions match.
public open operator fun <T : Any!> get(supplier: CheckedSupplier<TypeVariable(T)!>!): TypeVariable(T)! defined in dev.failsafe.FailsafeExecutor
public open operator fun <T : Any!> get(supplier: ContextualSupplier<TypeVariable(T)!, TypeVariable(T)!>!): TypeVariable(T)! defined in dev.failsafe.FailsafeExecutor

How can I specify the CheckedSupplier in Kotlin?

Thanks and Best regard

@hisano
Copy link

hisano commented Dec 26, 2024

You can specify CheckedSupplier using the following code.

Failsafe.with(retryPolicy).get(CheckedSupplier {
    ...
})

The code below is a simple example.

import dev.failsafe.Failsafe
import dev.failsafe.RetryPolicy
import dev.failsafe.function.CheckedSupplier

fun main() {
    val retryPolicy = RetryPolicy.builder<Int>().withMaxRetries(3).build()
    
    val result = Failsafe.with(retryPolicy).get(CheckedSupplier {
        1 + 2
    })

    println("result = $result")
}

@hisano
Copy link

hisano commented Dec 26, 2024

Creating functions like this makes the code easier to read in Kotlin.

operator fun <R> Policy<R>.invoke(block: ExecutionContext<R>.() -> R): R {
    try {
        return Failsafe.with(this).get { context -> context.block() }
    } catch (e: FailsafeException) {
        throw e.cause as Throwable
    }
}

The code below is a simple example.

import dev.failsafe.*
import java.io.IOException

fun main() {
    val retryWithIntResult = RetryPolicy.builder<Int>().withMaxRetries(3).build()
    val result = retryWithIntResult {
        println("attemptCount = $attemptCount")
        if (attemptCount == 3) {
            1 + 2
        } else {
            throw IOException()
        }
    }
    println("result = $result")

    val retryWithoutResult = RetryPolicy.builder<Unit>().withMaxRetries(3).build()
    retryWithoutResult {
        println("attemptCount = $attemptCount")
        if (attemptCount != 3) {
            throw IOException()
        }
    }
}

operator fun <R> Policy<R>.invoke(block: ExecutionContext<R>.() -> R): R {
    try {
        return Failsafe.with(this).get { context -> context.block() }
    } catch (e: FailsafeException) {
        throw e.cause as Throwable
    }
}

@hisano
Copy link

hisano commented Dec 26, 2024

As in this code, it may be better to standardize retries across the entire app, regardless of the return value type.

import dev.failsafe.*
import java.io.IOException
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.toJavaDuration

fun main() {
    fun <R> retry(block: ExecutionContext<R>.() -> R): R = RetryPolicy.builder<R>().withMaxRetries(3).withDelay(100.milliseconds.toJavaDuration()).build().invoke(block)

    val result = retry {
        println("attemptCount = $attemptCount")
        if (attemptCount == 3) {
            1 + 2
        } else {
            throw IOException()
        }
    }
    println("result = $result")

    retry {
        println("attemptCount = $attemptCount")
        if (attemptCount != 3) {
            throw IOException()
        }
    }
}

operator fun <R> Policy<R>.invoke(block: ExecutionContext<R>.() -> R): R {
    try {
        return Failsafe.with(this).get { context -> context.block() }
    } catch (e: FailsafeException) {
        throw e.cause as Throwable
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants