使用 Mutiny 实现重试逻辑
Implement retry logic with Mutiny
我刚开始学习 Mutiny,我需要实现重试逻辑。
我有这个代码:
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"))
}
因此,getResult()
是一个可能会出现异常的函数,需要在失败时多次调用。
当我运行这个程序时,是这样的:
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)
值得注意的是,getResult()
函数只被调用一次,而 onFailure()
阶段实际上执行了三次。
Mutiny 是否可以帮助我在每次失败时执行 getResult()
功能?我当然可以用一个简单的循环来实现它,但我觉得 Mutiny 应该已经有这样的东西了。
很遗憾,我没有在文档中找到合适的内容。
您在 getResult
中的 Uni 是使用“立即”项目创建的,该项目被缓存并且不再计算。
使用 Uni.createFrom().failure(() -> Exception("Some error happened"))
在本例中,它是一个供应商,因此它不会被缓存,但会在每次尝试时调用。
因此,正确的解决方案实际上是使用这样的 Uni.deferred()
方法:
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() }
)
}
感谢 Boris the Spider 建议使用 deferred()
,感谢 Clement,他阐明了空值的用法。
最初,我误解了 deferred()
文档,认为它不允许 return 一个空值,但实际上 Supplier
到 return 一个 Uni
为空:
Uni.createFrom.deferred { Uni.createFrom().nullItem() }
文档真正禁止的是 return 空而不是 Uni
:
Uni.createFrom().deferred { null }
我刚开始学习 Mutiny,我需要实现重试逻辑。
我有这个代码:
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"))
}
因此,getResult()
是一个可能会出现异常的函数,需要在失败时多次调用。
当我运行这个程序时,是这样的:
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)
值得注意的是,getResult()
函数只被调用一次,而 onFailure()
阶段实际上执行了三次。
Mutiny 是否可以帮助我在每次失败时执行 getResult()
功能?我当然可以用一个简单的循环来实现它,但我觉得 Mutiny 应该已经有这样的东西了。
很遗憾,我没有在文档中找到合适的内容。
您在 getResult
中的 Uni 是使用“立即”项目创建的,该项目被缓存并且不再计算。
使用 Uni.createFrom().failure(() -> Exception("Some error happened"))
在本例中,它是一个供应商,因此它不会被缓存,但会在每次尝试时调用。
因此,正确的解决方案实际上是使用这样的 Uni.deferred()
方法:
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() }
)
}
感谢 Boris the Spider 建议使用 deferred()
,感谢 Clement,他阐明了空值的用法。
最初,我误解了 deferred()
文档,认为它不允许 return 一个空值,但实际上 Supplier
到 return 一个 Uni
为空:
Uni.createFrom.deferred { Uni.createFrom().nullItem() }
文档真正禁止的是 return 空而不是 Uni
:
Uni.createFrom().deferred { null }