Reputation: 372
I'm just learning Mutiny and I need to implement retry logic.
I have this code:
fun main() {
getResult()
.onFailure().invoke { t -> println("Got error: $t") }
.onFailure().retry().atMost(2)
.subscribe().with(
{ result -> println(result) },
{ t -> t.printStackTrace() }
)
}
fun getResult(): Uni<String?> {
println("Preparing result...")
return Uni.createFrom().failure(Exception("Some error happened"))
}
So, the getResult()
is a function that may misbehave and needs to be called multiple times on failure.
When I run this program, this is what's happening:
Preparing result...
Got error: java.lang.Exception: Some error happened
Got error: java.lang.Exception: Some error happened
Got error: java.lang.Exception: Some error happened
java.lang.Exception: Some error happened
at MainKt.getResult(Main.kt:16)
at MainKt.main(Main.kt:4)
Obiously, the getResult()
function is called only once, while the onFailure()
stages actually executed three times.
Is there anything that Mutiny could help me to execute getResult()
function on each failure? I sure can implement this with a simple loop, but I feel like Mutiny should already have something like this.
Unfortunately, I didn't find anything suitable in the docs.
Upvotes: 1
Views: 1204
Reputation: 372
So, the right solution for this is actually using the Uni.deferred()
method like this:
fun main() {
Uni.createFrom().deferred { getResult() }
.onFailure().invoke { t -> println("Got error: $t") }
.onFailure().retry().atMost(2)
.subscribe().with(
{ result -> println(result) },
{ t -> t.printStackTrace() }
)
}
Thanks to Boris the Spider, who suggested to use the deferred()
, and to Clement, who clarified its use with null values.
Initially, I misinterpreted the deferred()
documentation thinking it's not allowed to return a null value, but actually it's OK for a Supplier
to return a Uni
of null:
Uni.createFrom.deferred { Uni.createFrom().nullItem() }
What the docs really are prohibiting is returning a null instead of a Uni
:
Uni.createFrom().deferred { null }
Upvotes: 2
Reputation: 3222
Your Uni in getResult
is created with an "immediate" item, which is cached and never computed again.
Use Uni.createFrom().failure(() -> Exception("Some error happened"))
In this case, it's a supplier, so it won't be cached but called on every attempt.
Upvotes: 2