
com.github.davidmoten.odata.client.Retries Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of odata-client-runtime Show documentation
Show all versions of odata-client-runtime Show documentation
OData client runtime for use with generated code
The newest version!
package com.github.davidmoten.odata.client;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.davidmoten.guavamini.Preconditions;
public final class Retries {
private static final Logger log = LoggerFactory.getLogger(Retries.class);
public static final Retries NONE = Retries.builder().maxRetries(0).keepGoingIf(t -> false).build();
private final long maxRetries;
private final Iterable retryIntervalsMs;
private final Supplier extends Function super Throwable, Boolean>> keepGoingIf;
Retries(long maxRetries, Iterable retryIntervalMs,
Supplier extends Function super Throwable, Boolean>> keepGoingIf) {
Preconditions.checkArgument(maxRetries >= 0);
Preconditions.checkNotNull(retryIntervalMs);
Preconditions.checkNotNull(keepGoingIf);
this.maxRetries = maxRetries;
this.retryIntervalsMs = retryIntervalMs;
this.keepGoingIf = keepGoingIf;
}
public void performWithRetries(RunnableThrowing runnable) {
int attempt = 0;
Throwable error = null;
Function super Throwable, Boolean> keepGoing = keepGoingIf().get();
Iterator intervalsMs = retryIntervalsMs().iterator();
while (true) {
if (attempt > maxRetries()) {
throw new RetryException("attempts greater than maxRetries", error);
}
attempt++;
try {
runnable.run();
break;
} catch (Throwable e) {
error = e;
log.debug(e.getMessage(), e);
if (!keepGoing.apply(e)) {
throw new RetryException("exception not retryable", e);
}
if (!intervalsMs.hasNext()) {
throw new RetryException("stopping retries because no more intervals specified");
}
long waitMs = intervalsMs.next();
log.debug("sleeping " + waitMs + "ms");
sleep(waitMs);
}
}
}
public static Builder builder() {
return new Builder();
}
public long maxRetries() {
return maxRetries;
}
public Iterable retryIntervalsMs() {
return retryIntervalsMs;
}
public Supplier extends Function super Throwable, Boolean>> keepGoingIf() {
return keepGoingIf;
}
private static final class ForeverZero implements Iterable {
@Override
public Iterator iterator() {
return new ForeverZeroIterator();
}
}
private static final class ForeverZeroIterator implements Iterator {
@Override
public boolean hasNext() {
return true;
}
@Override
public Long next() {
return 0L;
}
}
public static final class Builder {
private static final Iterable NO_INTERVAL = new ForeverZero();
private long maxRetries = 0;
private Iterable retryIntervalsMs = NO_INTERVAL;
private Supplier extends Function super Throwable, Boolean>> keepGoingIf = () -> (t -> !(t instanceof Error));
Builder() {
}
public Builder maxRetries(long maxRetries) {
this.maxRetries = maxRetries;
return this;
}
public Builder retryIntervalsMs(Iterable retryIntervalsMs) {
this.retryIntervalsMs = retryIntervalsMs;
return this;
}
public Builder keepGoingIf(Function super Throwable, Boolean> keepGoingIf) {
this.keepGoingIf = () -> keepGoingIf;
return this;
}
public Builder keepGoingIf(Supplier extends Function super Throwable, Boolean>> keepGoingIf) {
this.keepGoingIf = keepGoingIf;
return this;
}
public Builder retryIntervals(Iterable retryIntervals, TimeUnit unit) {
return retryIntervalsMs(createRetryIntervalMsIterable(retryIntervals, unit));
}
private static Iterable createRetryIntervalMsIterable(Iterable retryIntervals, TimeUnit unit) {
return new Iterable() {
@Override
public Iterator iterator() {
Iterator it = retryIntervals.iterator();
return new Iterator() {
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public Long next() {
return unit.toMillis(it.next());
}
};
}
};
}
public Builder cappedExponentialRetry(long initial, double factor, long cap, TimeUnit unit) {
Preconditions.checkArgument(initial >= 0);
Preconditions.checkArgument(factor >= 0);
Preconditions.checkArgument(cap >= 0);
Preconditions.checkNotNull(unit);
return retryIntervalsMs(createCappedExponentialRetryIterable(initial, factor, cap, unit));
}
private static Iterable createCappedExponentialRetryIterable(long initial, double factor, long cap, TimeUnit unit) {
return new Iterable() {
@Override
public Iterator iterator() {
return new Iterator() {
long v = initial;
@Override
public boolean hasNext() {
return true;
}
@Override
public Long next() {
long w = v;
v = Math.round(Math.min(v * factor, cap));
return unit.toMillis(w);
}
};
}
};
}
public Retries build() {
return new Retries(maxRetries, retryIntervalsMs, keepGoingIf);
}
}
private static void sleep(long waitMs) {
try {
Thread.sleep(waitMs);
} catch (InterruptedException interruptedException) {
throw new RetryException("interrupted", interruptedException);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy