com.couchbase.client.core.retry.reactor.Repeat Maven / Gradle / Ivy
Show all versions of core-io Show documentation
/*
* Copyright (c) 2017 Pivotal Software Inc, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.couchbase.client.core.retry.reactor;
import com.couchbase.client.core.error.InvalidArgumentException;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import java.time.Duration;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* Repeat function that may be used with {@link Flux#repeatWhen(Function)},
* {@link Mono#repeatWhen(Function)} and {@link Mono#repeatWhenEmpty(Function)}.
*
* Each change in configuration returns a new instance (copy configuration), which
* makes {@link Repeat} suitable for creating configuration templates that can be fine
* tuned for specific cases without impacting the original general use-case configuration.
*
* Example usage:
*
* repeat = Repeat.times(10)
* .randomBackoff(Duration.ofMillis(100), Duration.ofSeconds(60))
* .withApplicationContext(appContext)
* .doOnRepeat(context -> context.applicationContext().rollback());
* flux.repeatWhen(repeat);
*
*
* @param Application context type
*/
public interface Repeat extends Function, Publisher> {
/**
* Repeat function that repeats only if the predicate returns true.
* @param predicate Predicate that determines if next repeat is performed
* @return Repeat function with predicate
*/
static Repeat onlyIf(Predicate> predicate) {
return DefaultRepeat.create(predicate, Long.MAX_VALUE);
}
/**
* Repeat function that repeats once.
* @return Repeat function for one repeat
*/
static Repeat once() {
return times(1L);
}
/**
* Repeat function that repeats n times.
* @param n number of repeats
* @return Repeat function for n repeats
*/
static Repeat times(long n) {
if (n < 0)
throw InvalidArgumentException.fromMessage("n should be >= 0");
return DefaultRepeat.create(context -> true, n);
}
/**
* Repeat function that repeats n times, only if the predicate returns true.
* @param predicate Predicate that determines if next repeat is performed
* @param n number of repeats
* @return Repeat function with predicate and n repeats
*/
static Repeat create(Predicate> predicate, long n) {
return DefaultRepeat.create(predicate, n);
}
/**
* Returns a repeat function with an application context that may be
* used to perform any rollbacks before a repeat. This application
* context is provided to any repeat predicate {@link #onlyIf(Predicate)},
* custom backoff function {@link #backoff(Backoff)} and repeat
* callback {@link #doOnRepeat(Consumer)}. All other properties of
* this repeat function are retained in the returned instance.
*
* @param applicationContext Application context
* @return repeat function with associated application context
*/
Repeat withApplicationContext(T applicationContext);
/**
* Returns a repeat function that invokes the provided onRepeat
* callback before every repeat. The {@link RepeatContext} provided
* to the callback contains the iteration and the any application
* context set using {@link #withApplicationContext(Object)}.
* All other properties of this repeat function are retained in the
* returned instance.
*
* @param onRepeat callback to invoke before repeats
* @return repeat function with callback
*/
Repeat doOnRepeat(Consumer> onRepeat);
/**
* Returns a repeat function with timeout. The timeout starts from
* the instant that this function is applied and switches to unlimited
* number of attempts. All other properties of
* this repeat function are retained in the returned instance.
*
* @param timeout timeout after which no new repeats are initiated
* @return repeat function with timeout
*/
Repeat timeout(Duration timeout);
/**
* Returns a repeat function that repeats at most n times. All other
* properties of this repeat function are retained in the returned instance.
*
* @param maxRepeats number of repeats
* @return Retry function for n repeats
*/
Repeat repeatMax(long maxRepeats);
/**
* Returns a repeat function with backoff delay.
* All other properties of this repeat function are retained in the
* returned instance.
*
* @param backoff the backoff function to determine backoff delay
* @return repeat function with backoff
*/
Repeat backoff(Backoff backoff);
/**
* Returns a repeat function that applies jitter to the backoff delay.
* All other properties of this repeat function are retained in the
* returned instance.
*
* @param jitter Jitter function to randomize backoff delay
* @return repeat function with jitter for backoff
*/
Repeat jitter(Jitter jitter);
/**
* Returns a repeat function that uses the scheduler provided for
* backoff delays. All other properties of this repeat function
* are retained in the returned instance.
* @param scheduler the scheduler for backoff delays
* @return repeat function with backoff scheduler
*/
Repeat withBackoffScheduler(Scheduler scheduler);
/**
* Returns a repeat function with no backoff delay. This is the default.
* All other properties of this repeat function are retained in the
* returned instance.
*
* @return repeat function with no backoff delay
*/
default Repeat noBackoff() {
return backoff(Backoff.zero());
}
/**
* Returns a repeat function with fixed backoff delay.
* All other properties of this repeat function are retained in the
* returned instance.
*
* @param backoffInterval fixed backoff delay applied before every repeat
* @return repeat function with fixed backoff delay
*/
default Repeat fixedBackoff(Duration backoffInterval) {
return backoff(Backoff.fixed(backoffInterval));
}
/**
* Returns a repeat function with exponential backoff delay.
* All other properties of this repeat function are retained in the
* returned instance.
*
* Repeats are performed after a backoff interval of firstBackoff * (2 ** n)
* where n is the next iteration number. If maxBackoff
is not null, the maximum
* backoff applied will be limited to maxBackoff
.
*
* @param firstBackoff the delay for the first backoff, which is also used as the coefficient for subsequent backoffs
* @param maxBackoff the maximum backoff delay before a repeat
* @return repeat function with exponential backoff delay
*/
default Repeat exponentialBackoff(Duration firstBackoff, Duration maxBackoff) {
return backoff(Backoff.exponential(firstBackoff, maxBackoff, 2, false));
}
/**
* Returns a repeat function with full jitter backoff strategy.
* All other properties of this repeat function are retained in the
* returned instance.
*
* Repeats are performed after a random backoff interval between firstBackoff
and
* firstBackoff * (2 ** n)
where n is the next iteration number. If maxBackoff
* is not null, the maximum backoff applied will be limited to maxBackoff
.
*
* @param firstBackoff the delay for the first backoff, which is also used as the coefficient for subsequent backoffs
* @param maxBackoff the maximum backoff delay before a repeat
* @return repeat function with full jitter backoff strategy
*/
default Repeat exponentialBackoffWithJitter(Duration firstBackoff, Duration maxBackoff) {
return backoff(Backoff.exponential(firstBackoff, maxBackoff, 2, false)).jitter(Jitter.random());
}
/**
* Returns a repeat function with random de-correlated jitter backoff strategy.
* All other properties of this repeat function are retained in the
* returned instance.
*
* Repeats are performed after a backoff interval of random_between(firstBackoff, prevBackoff * 3)
,
* with a minimum value of firstBackoff
. If maxBackoff
* is not null, the maximum backoff applied will be limited to maxBackoff
.
*
* @param firstBackoff the delay for the first backoff, also used as minimum backoff
* @param maxBackoff the maximum backoff delay before a repeat
* @return repeat function with de-correlated jitter backoff strategy
*/
default Repeat randomBackoff(Duration firstBackoff, Duration maxBackoff) {
return backoff(Backoff.exponential(firstBackoff, maxBackoff, 3, true)).jitter(Jitter.random());
}
/**
* Transforms the source into a repeating {@link Flux} based on the properties
* configured for this function.
*
* Example usage:
*
* repeat = Repeat.times(n)
* .exponentialBackoff(Duration.ofMillis(100), Duration.ofSeconds(60));
* flux.as(repeat);
*
*
* @param source the source publisher
* @return {@link Flux} with the repeat properties of this repeat function
*/
default Flux apply(Publisher source) {
return Flux.from(source).repeatWhen(this);
}
}