com.couchbase.client.core.retry.reactor.DefaultRetry 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.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.Predicate;
public class DefaultRetry extends AbstractRetry implements Retry {
static final Consumer> NOOP_ON_RETRY = r -> {};
final Predicate> retryPredicate;
final Consumer> onRetry;
DefaultRetry(Predicate> retryPredicate,
long maxIterations,
Duration timeout,
Backoff backoff,
Jitter jitter,
Scheduler backoffScheduler,
final Consumer> onRetry,
T applicationContext) {
super(maxIterations, timeout, backoff, jitter, backoffScheduler, applicationContext);
this.retryPredicate = retryPredicate;
this.onRetry = onRetry;
}
public static DefaultRetry create(Predicate> retryPredicate) {
return new DefaultRetry(retryPredicate,
Long.MAX_VALUE,
null,
Backoff.zero(),
Jitter.noJitter(),
null,
NOOP_ON_RETRY,
(T) null);
}
@Override
public Retry withApplicationContext(T applicationContext) {
return new DefaultRetry<>(retryPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRetry, applicationContext);
}
@Override
public Retry doOnRetry(Consumer> onRetry) {
return new DefaultRetry<>(retryPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRetry, applicationContext);
}
@Override
public Retry retryMax(long maxIterations) {
if (maxIterations < 0)
throw InvalidArgumentException.fromMessage("maxIterations should be >= 0");
return new DefaultRetry<>(retryPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRetry, applicationContext);
}
@Override
public Retry timeout(Duration timeout) {
if (timeout.isNegative())
throw InvalidArgumentException.fromMessage("timeout should be >= 0");
return new DefaultRetry<>(retryPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRetry, applicationContext);
}
@Override
public Retry backoff(Backoff backoff) {
return new DefaultRetry<>(retryPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRetry, applicationContext);
}
@Override
public Retry jitter(Jitter jitter) {
return new DefaultRetry<>(retryPredicate, maxIterations, timeout,
backoff, jitter, backoffScheduler, onRetry, applicationContext);
}
@Override
public Retry withBackoffScheduler(Scheduler scheduler) {
return new DefaultRetry<>(retryPredicate, maxIterations, timeout,
backoff, jitter, scheduler, onRetry, applicationContext);
}
@Override
public Publisher apply(Flux errors) {
Instant timeoutInstant = calculateTimeout();
DefaultContext context = new DefaultContext<>(applicationContext, 0L, null, null);
return errors.index()
.concatMap(tuple -> retry(tuple.getT2(), tuple.getT1() + 1L, timeoutInstant, context));
}
Publisher retry(Throwable e, long iteration, Instant timeoutInstant, DefaultContext context) {
DefaultContext tmpContext = new DefaultContext<>(applicationContext, iteration, context.lastBackoff, e);
BackoffDelay nextBackoff = calculateBackoff(tmpContext, timeoutInstant);
DefaultContext retryContext = new DefaultContext(applicationContext, iteration, nextBackoff, e);
context.lastBackoff = nextBackoff;
if (!retryPredicate.test(retryContext)) {
return Mono.error(e);
}
else if (nextBackoff == RETRY_EXHAUSTED) {
return Mono.error(new RetryExhaustedException(e));
}
else {
onRetry.accept(retryContext);
return retryMono(nextBackoff.delay());
}
}
@Override
public String toString() {
return "Retry{max=" + this.maxIterations + ",backoff=" + backoff + ",jitter=" +
jitter + "}";
}
}