我正在尝试仅使用Kotlin flow
来实施退避策略。
我需要从timeA到timeB取数据
result = dataBetween(timeA - timeB)
如果结果为空,那么我想使用指数补偿增加结束时间窗口
result = dataBetween(timeA - timeB + exponentialBackOffInDays)
我关注的是这篇文章,其中介绍了如何在rxjava2
中实现这一目标。
但是在flow
没有takeUntil
运算符yet的情况下陷入困境。
您可以在下面查看我的实施情况。
fun main() {
runBlocking {
(0..8).asFlow()
.flatMapConcat { input ->
// To simulate a data source which fetches data based on a time-window start-date to end-date
// available with in that time frame.
flow {
println("Input: $input")
if (input < 5) {
emit(emptyList<String>())
} else { // After emitting this once the flow should complete
emit(listOf("Available"))
}
}.retryWhenThrow(DummyException(), predicate = {
it.isNotEmpty()
})
}.collect {
//println(it)
}
}
}
class DummyException : Exception("Collected size is empty")
private inline fun <T> Flow<T>.retryWhenThrow(
throwable: Throwable,
crossinline predicate: suspend (T) -> Boolean
): Flow<T> {
return flow {
collect { value ->
if (!predicate(value)) {
throw throwable // informing the upstream to keep emitting since the condition is met
}
println("Value: $value")
emit(value)
}
}.catch { e ->
if (e::class != throwable::class) throw e
}
}
工作正常,除非流量具有成功的值,但流量仍继续从上游流量收集到8
,但理想情况下,流量应在到达5
本身时停止。
任何有关如何解决此问题的帮助都会有所帮助。
答案 0 :(得分:0)
也许这与您的确切设置不符,但您最好不使用collect
或first{...}
来调用firstOrNull{...}
找到元素后,这将自动停止上游流。
例如:
flowOf(0,0,3,10)
.flatMapConcat {
println("creating list with $it elements")
flow {
val listWithElementCount = MutableList(it){ "" } // just a list of n empty strings
emit(listWithElementCount)
}
}.first { it.isNotEmpty() }
在旁注中,您的问题听起来像是常规的暂挂功能更合适。 像
suspend fun getFirstNonEmptyList(initialFrom: Long, initialTo: Long): List<Any> {
var from = initialFrom
var to = initialTo
while (coroutineContext.isActive) {
val elements = getElementsInRange(from, to) // your "dataBetween"
if (elements.isNotEmpty()) return elements
val (newFrom, newTo) = nextBackoff(from, to)
from = newFrom
to = newTo
}
throw CancellationException()
}