class 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);

}