com.couchbase.client.core.retry.reactor.DefaultRepeat Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-io Show documentation
Show all versions of core-io Show documentation
The official Couchbase JVM Core IO Library
/*
* 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.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import java.time.Duration;
import java.time.Instant;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
public class DefaultRepeat extends AbstractRetry implements Repeat {
static final Consumer> NOOP_ON_REPEAT = r -> {};
final Predicate> repeatPredicate;
final Consumer> onRepeat;
DefaultRepeat(Predicate> repeatPredicate,
long maxRepeats,
Duration timeout,
Backoff backoff,
Jitter jitter,
Scheduler backoffScheduler,
final Consumer> onRepeat,
T applicationContext) {
super(maxRepeats, timeout, backoff, jitter, backoffScheduler, applicationContext);
this.repeatPredicate = repeatPredicate;
this.onRepeat = onRepeat;
}
public static DefaultRepeat create(Predicate> repeatPredicate, long n) {
return new DefaultRepeat(repeatPredicate,
n,
null,
Backoff.zero(),
Jitter.noJitter(),
null,
NOOP_ON_REPEAT,
(T) null);
}
@Override
public Repeat withApplicationContext(T applicationContext) {
return new DefaultRepeat<>(repeatPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRepeat, applicationContext);
}
@Override
public Repeat doOnRepeat(Consumer> onRepeat) {
return new DefaultRepeat<>(repeatPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRepeat, applicationContext);
}
@Override
public Repeat timeout(Duration timeout) {
if (timeout.isNegative())
throw InvalidArgumentException.fromMessage("timeout should be >= 0");
return new DefaultRepeat<>(repeatPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRepeat, applicationContext);
}
@Override
public Repeat repeatMax(long maxRepeats) {
if (maxRepeats < 1)
throw InvalidArgumentException.fromMessage("maxRepeats should be > 0");
return new DefaultRepeat<>(repeatPredicate, maxRepeats, timeout, backoff, jitter,
backoffScheduler, onRepeat, applicationContext);
}
@Override
public Repeat backoff(Backoff backoff) {
return new DefaultRepeat<>(repeatPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRepeat, applicationContext);
}
@Override
public Repeat jitter(Jitter jitter) {
return new DefaultRepeat<>(repeatPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRepeat, applicationContext);
}
@Override
public Repeat withBackoffScheduler(Scheduler scheduler) {
return new DefaultRepeat<>(repeatPredicate, maxIterations, timeout,
backoff, jitter, scheduler, onRepeat, applicationContext);
}
@Override
public Publisher apply(Flux companionValues) {
Instant timeoutInstant = calculateTimeout();
DefaultContext context = new DefaultContext<>(applicationContext, 0, null, -1L);
return companionValues
.index()
.map(tuple -> repeatBackoff(tuple.getT2(), tuple.getT1() + 1L, timeoutInstant, context))
.takeWhile(backoff -> backoff != RETRY_EXHAUSTED)
.concatMap(backoff -> retryMono(backoff.delay).onErrorResume(Exceptions::isOverflow, throwable -> Mono.just(1L)));
}
BackoffDelay repeatBackoff(Long companionValue, Long iteration, Instant timeoutInstant, DefaultContext context) {
DefaultContext tmpContext = new DefaultContext<>(applicationContext, iteration, context.lastBackoff, companionValue);
BackoffDelay nextBackoff = calculateBackoff(tmpContext, timeoutInstant);
DefaultContext repeatContext = new DefaultContext<>(applicationContext, iteration, nextBackoff, companionValue);
context.lastBackoff = nextBackoff;
if (!repeatPredicate.test(repeatContext)) {
return RETRY_EXHAUSTED;
}
else if (nextBackoff == RETRY_EXHAUSTED) {
return RETRY_EXHAUSTED;
}
else {
onRepeat.accept(repeatContext);
return nextBackoff;
}
}
@Override
public String toString() {
return "Repeat{times=" + this.maxIterations + ",backoff=" + backoff + ",jitter=" +
jitter + "}";
}
}