spring-retry
spring-retry copied to clipboard
Spring Retry not working with Kotlin Async Coroutine
Note: the below function test is being called via a launch coroutine.
The following code works:
@Retryable(value=[RetryException::class])
suspend fun test() {
throw RetryException("blah")
}
However, the moment I add an async call, retry stops working:
@Retryable(value=[RetryException::class])
suspend fun test() {
val deferred = supervisorScope {
async { library.method() }
}
deferred.await()
throw RetryException("blah")
}
What could be wrong?
The @Retryable
creates a proxy call around the method with try...catch
.
I don't think that Kotlin async
behavior does fit into the try...catch
model.
It might be great to see a generated Java code back from this Kotlin to determine when exactly that @Retryable
sits in the call stack.
It is very likely that there are some anonymous classes are generated and their method calls are done in the separate thread which is already out of retry proxy.
You can find more information on Coroutines exception handling here. Maybe worth to have a reproducer to analyze the behavior and evaluate if that makes sense to support it.
If not supported, maybe worth to throw an early error at startup if possible and document it is not supported, leveraging KotlinDetector.isSuspendingFunction()
to avoid silent failures.
Not sure if that matters here, but from a bytecode / Java reflection perspective, suspend fun test()
in Kotlin will be translated to something like Object test(Continuation continuation)
in Java, so to get the real signature you need to identify suspending functions with KotlinDetector.isSuspendingFunction()
and then for example use Kotlin reflection to get the real return value / parameter via ReflectJvmMapping.getKotlinFunction
(see usages in Spring Framework). Also if you want to re-invoke the suspending function, you probably need to leverage Kotlin reflection API as well.