@Test void calculateBackoffUsesDefaultClockWhenNoScheduler() { Instant timeoutInstant = Instant.now().plusSeconds(3); AbstractRetry<String, Integer> abstractRetry = new AbstractRetry<String, Integer>(2, Duration.ofSeconds(1), Backoff.fixed(Duration.ofMillis(600)), Jitter.NO_JITTER, null, null) { @Override public Publisher<Long> apply(Flux<Integer> integerFlux) { return null; } }; RetryContext<String> retryContext = new DefaultContext<>(null, 1, BackoffDelay.ZERO, null); BackoffDelay backoff = abstractRetry.calculateBackoff(retryContext, timeoutInstant); assertNotEquals(backoff, AbstractRetry.RETRY_EXHAUSTED); assertEquals(backoff.delay, Duration.ofMillis(600)); }
BackoffDelay calculateBackoff(IterationContext<T> retryContext, Instant timeoutInstant) { if (retryContext.iteration() > maxIterations) return RETRY_EXHAUSTED; BackoffDelay nextBackoff = backoff.apply(retryContext); Duration minBackoff = nextBackoff.min; Duration maxBackoff = nextBackoff.max; Duration backoff = nextBackoff.delay; if (maxBackoff != null) backoff = backoff.compareTo(maxBackoff) < 0 ? backoff : maxBackoff; if (minBackoff != null) backoff = backoff.compareTo(minBackoff) > 0 ? backoff : minBackoff; BackoffDelay sanitizedBackoff = new BackoffDelay(minBackoff, maxBackoff, backoff); Duration jitteredBackoff = jitter.apply(sanitizedBackoff); if (Instant.now(clock).plus(jitteredBackoff).isAfter(timeoutInstant)) return RETRY_EXHAUSTED; else return new BackoffDelay(minBackoff, maxBackoff, jitteredBackoff); }
AbstractRetry implements Function<Flux<S>, Publisher<Long>> { BackoffDelay calculateBackoff(IterationContext<T> retryContext, Instant timeoutInstant) { if (retryContext.iteration() > maxIterations) return RETRY_EXHAUSTED; BackoffDelay nextBackoff = backoff.apply(retryContext); Duration minBackoff = nextBackoff.min; Duration maxBackoff = nextBackoff.max; Duration backoff = nextBackoff.delay; if (maxBackoff != null) backoff = backoff.compareTo(maxBackoff) < 0 ? backoff : maxBackoff; if (minBackoff != null) backoff = backoff.compareTo(minBackoff) > 0 ? backoff : minBackoff; BackoffDelay sanitizedBackoff = new BackoffDelay(minBackoff, maxBackoff, backoff); Duration jitteredBackoff = jitter.apply(sanitizedBackoff); if (Instant.now(clock).plus(jitteredBackoff).isAfter(timeoutInstant)) return RETRY_EXHAUSTED; else return new BackoffDelay(minBackoff, maxBackoff, jitteredBackoff); } }
AbstractRetry implements Function<Flux<S>, Publisher<Long>> { BackoffDelay calculateBackoff(IterationContext<T> retryContext, Instant timeoutInstant) { if (retryContext.iteration() > maxIterations) return RETRY_EXHAUSTED; BackoffDelay nextBackoff = backoff.apply(retryContext); Duration minBackoff = nextBackoff.min; Duration maxBackoff = nextBackoff.max; Duration backoff = nextBackoff.delay; if (maxBackoff != null) backoff = backoff.compareTo(maxBackoff) < 0 ? backoff : maxBackoff; if (minBackoff != null) backoff = backoff.compareTo(minBackoff) > 0 ? backoff : minBackoff; BackoffDelay sanitizedBackoff = new BackoffDelay(minBackoff, maxBackoff, backoff); Duration jitteredBackoff = jitter.apply(sanitizedBackoff); if (Instant.now(clock).plus(jitteredBackoff).isAfter(timeoutInstant)) return RETRY_EXHAUSTED; else return new BackoffDelay(minBackoff, maxBackoff, jitteredBackoff); } AbstractRetry(long maxIterations,
			Duration timeout,
			Backoff backoff,
			Jitter jitter,
			@Nullable
			Scheduler backoffScheduler,
			T applicationContext); }
AbstractRetry implements Function<Flux<S>, Publisher<Long>> { BackoffDelay calculateBackoff(IterationContext<T> retryContext, Instant timeoutInstant) { if (retryContext.iteration() > maxIterations) return RETRY_EXHAUSTED; BackoffDelay nextBackoff = backoff.apply(retryContext); Duration minBackoff = nextBackoff.min; Duration maxBackoff = nextBackoff.max; Duration backoff = nextBackoff.delay; if (maxBackoff != null) backoff = backoff.compareTo(maxBackoff) < 0 ? backoff : maxBackoff; if (minBackoff != null) backoff = backoff.compareTo(minBackoff) > 0 ? backoff : minBackoff; BackoffDelay sanitizedBackoff = new BackoffDelay(minBackoff, maxBackoff, backoff); Duration jitteredBackoff = jitter.apply(sanitizedBackoff); if (Instant.now(clock).plus(jitteredBackoff).isAfter(timeoutInstant)) return RETRY_EXHAUSTED; else return new BackoffDelay(minBackoff, maxBackoff, jitteredBackoff); } AbstractRetry(long maxIterations,
			Duration timeout,
			Backoff backoff,
			Jitter jitter,
			@Nullable
			Scheduler backoffScheduler,
			T applicationContext);  }
AbstractRetry implements Function<Flux<S>, Publisher<Long>> { BackoffDelay calculateBackoff(IterationContext<T> retryContext, Instant timeoutInstant) { if (retryContext.iteration() > maxIterations) return RETRY_EXHAUSTED; BackoffDelay nextBackoff = backoff.apply(retryContext); Duration minBackoff = nextBackoff.min; Duration maxBackoff = nextBackoff.max; Duration backoff = nextBackoff.delay; if (maxBackoff != null) backoff = backoff.compareTo(maxBackoff) < 0 ? backoff : maxBackoff; if (minBackoff != null) backoff = backoff.compareTo(minBackoff) > 0 ? backoff : minBackoff; BackoffDelay sanitizedBackoff = new BackoffDelay(minBackoff, maxBackoff, backoff); Duration jitteredBackoff = jitter.apply(sanitizedBackoff); if (Instant.now(clock).plus(jitteredBackoff).isAfter(timeoutInstant)) return RETRY_EXHAUSTED; else return new BackoffDelay(minBackoff, maxBackoff, jitteredBackoff); } AbstractRetry(long maxIterations,
			Duration timeout,
			Backoff backoff,
			Jitter jitter,
			@Nullable
			Scheduler backoffScheduler,
			T applicationContext);   }