Пользовательская повторная попытка в Reactor
Я пытался реализовать логику повторов в Kotlin и Reactor, основываясь на возможностях дополнительного пакета Reactor. То, что я пытаюсь сделать, это передать список продолжительности, и на каждом context.iteration
Я получаю (iteration-1) -й элемент списка. Это работает частично, я всегда получаю IndexOutOfBoundsException
на последней итерации, что больше, чем я хотел, хотя я предоставил максимальное количество повторов - размер списка. Тем не менее, повторные попытки выполняются с заданной продолжительностью и "правильным" числом раз (конечно, потому что IndexOutOfBoundsException
мешает больше), только это исключение (и его первопричина) беспокоит меня.
Это мой пользовательский интерфейс BackOff:
interface MyCustomBackoff : Backoff {
companion object {
fun getBackoffDelay(backoffList: List<Duration>): (IterationContext<*>) -> BackoffDelay {
return { context -> BackoffDelay(backoffList[(context.iteration() - 1).toInt()]) }
}
}
}
И мое расширение Kotlin:
fun <T> Mono<T>.retryCustomBackoffs(backoffList: List<Duration>, doOnRetry: ((RetryContext<T>) -> Unit)? = null): Mono<T> {
val retry = Retry.any<T>().retryMax(backoffList.size.toLong()).backoff(MyCustomBackoff.getBackoffDelay(backoffList))
return if (doOnRetry == null) {
this.retryWhen(retry)
}
else {
this.retryWhen(retry.doOnRetry(doOnRetry))
}
}
Что мне здесь не хватает?
1 ответ
Если вы посмотрите на reactor.retry.AbstractRetry#calculateBackoff
Вы могли найти, что есть специальные BackoffDelay
названный RETRY_EXHAUSTED
, И это возвращается, когда retryContext.iteration() > maxIterations
(не >=
) после backoff.apply(retryContext)
if (retryContext.iteration() > maxIterations || Instant.now(clock).plus(jitteredBackoff).isAfter(timeoutInstant))
return RETRY_EXHAUSTED;
Таким образом, если у вас есть 2 пользовательские задержки отката в списке, будет 3 задержки отсрочки, сгенерированные calculateBackoff
,
Вы можете изменить свой MyCustomBackoff
вот так (извините за Java, я не знаком с Kotlin):
public interface MyCustomBackoff extends Backoff {
static Backoff getBackoffDelay(List<Duration> backoffList) {
return context -> context.iteration() <= backoffList.size() ?
new BackoffDelay(backoffList.get(Long.valueOf(context.iteration() - 1).intValue())) :
new BackoffDelay(Duration.ZERO);
}
}