1

我只是在学习 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()阶段实际上执行了 3 次。

Mutiny 有什么可以帮助我getResult()在每次失败时执行功能的吗?我当然可以用一个简单的循环来实现它,但我觉得 Mutiny 应该已经有了这样的东西。

不幸的是,我在文档中没有找到任何合适的东西。

4

2 回答 2

1

因此,正确的解决方案实际上是使用这样的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,他建议使用deferred(),并感谢 Clement,他澄清了使用 null 值。

最初,我误解了deferred()文档,认为它不允许返回 null 值,但实际上 aSupplier返回Uninull 是可以的:

Uni.createFrom.deferred { Uni.createFrom().nullItem() }

文档真正禁止的是返回 null 而不是 a Uni

Uni.createFrom().deferred { null }

于 2022-01-30T15:34:26.807 回答
1

您的 Uni ingetResult是使用“立即”项目创建的,该项目被缓存并且永远不会再次计算。

利用 Uni.createFrom().failure(() -> Exception("Some error happened"))

在这种情况下,它是一个供应商,所以它不会被缓存,但每次尝试都会调用它。

于 2022-01-26T08:52:28.343 回答