All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.camunda.operate.util.RetryOperation Maven / Gradle / Ivy
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
* one or more contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright ownership.
* Licensed under the Camunda License 1.0. You may not use this file
* except in compliance with the Camunda License 1.0.
*/
package io.camunda.operate.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//
// Taken from https://stackoverflow.com/questions/13239972/how-do-you-implement-a-re-try-catch and
// slightly modified
//
public final class RetryOperation {
private static final Logger LOGGER = LoggerFactory.getLogger(RetryOperation.class);
private RetryConsumer retryConsumer;
private int noOfRetry;
private int delayInterval;
private TimeUnit timeUnit;
private RetryPredicate retryPredicate;
private List> exceptionList;
private String message;
private RetryOperation(
RetryConsumer retryConsumer,
int noOfRetry,
int delayInterval,
TimeUnit timeUnit,
RetryPredicate retryPredicate,
List> exceptionList,
String message) {
this.retryConsumer = retryConsumer;
this.noOfRetry = noOfRetry;
this.delayInterval = delayInterval;
this.timeUnit = timeUnit;
this.retryPredicate = retryPredicate;
this.exceptionList = exceptionList;
this.message = message;
}
public static OperationBuilder newBuilder() {
return new OperationBuilder<>();
}
public T retry() throws Exception {
T result = null;
int retries = 0;
while (retries < noOfRetry) {
try {
result = retryConsumer.evaluate();
if (Objects.nonNull(retryPredicate)) {
final boolean shouldItRetry = retryPredicate.shouldRetry(result);
if (shouldItRetry) {
retries = increaseRetryCountAndSleep(retries);
} else {
return result;
}
} else {
// no retry condition defined, no exception thrown. This is the desired result.
return result;
}
} catch (Exception e) {
LOGGER.warn(String.format("Retry Operation %s failed: %s", message, e.getMessage()), e);
retries = handleException(retries, e);
}
}
return result;
}
private int handleException(int retries, Exception e) throws Exception {
if (exceptionList.isEmpty()
|| exceptionList.stream().anyMatch(ex -> ex.isAssignableFrom(e.getClass()))) {
// exception is accepted, continue retry.
retries = increaseRetryCountAndSleep(retries);
if (retries == noOfRetry) {
// evaluation is throwing exception, no more retry left. Throw it.
throw e;
}
} else {
// unexpected exception, no retry required. Throw it.
throw e;
}
return retries;
}
private int increaseRetryCountAndSleep(int retries) {
retries++;
if (retries < noOfRetry && delayInterval > 0) {
try {
if (retries % 20 == 0) {
LOGGER.info(
"{} - Waiting {} {}. {}/{}", message, delayInterval, timeUnit, retries, noOfRetry);
} else {
LOGGER.debug(
"{} - Waiting {} {}. {}/{}", message, delayInterval, timeUnit, retries, noOfRetry);
}
timeUnit.sleep(delayInterval);
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
}
}
return retries;
}
public static final class OperationBuilder {
private RetryConsumer iRetryConsumer;
private int iNoOfRetry;
private int iDelayInterval;
private TimeUnit iTimeUnit;
private RetryPredicate iRetryPredicate;
private Class extends Throwable>[] exceptionClasses;
private String message = "";
private OperationBuilder() {}
public OperationBuilder retryConsumer(final RetryConsumer retryConsumer) {
this.iRetryConsumer = retryConsumer;
return this;
}
public OperationBuilder noOfRetry(final int noOfRetry) {
this.iNoOfRetry = noOfRetry;
return this;
}
public OperationBuilder delayInterval(final int delayInterval, final TimeUnit timeUnit) {
this.iDelayInterval = delayInterval;
this.iTimeUnit = timeUnit;
return this;
}
public OperationBuilder retryPredicate(final RetryPredicate retryPredicate) {
this.iRetryPredicate = retryPredicate;
return this;
}
@SafeVarargs
public final OperationBuilder retryOn(final Class extends Throwable>... exceptionClasses) {
this.exceptionClasses = exceptionClasses;
return this;
}
public OperationBuilder message(final String message) {
this.message = message;
return this;
}
public RetryOperation build() {
if (Objects.isNull(iRetryConsumer)) {
throw new RuntimeException("'#retryConsumer:RetryConsumer' not set");
}
List> exceptionList = new ArrayList<>();
if (Objects.nonNull(exceptionClasses) && exceptionClasses.length > 0) {
exceptionList = Arrays.asList(exceptionClasses);
}
iNoOfRetry = iNoOfRetry == 0 ? 1 : iNoOfRetry;
iTimeUnit = Objects.isNull(iTimeUnit) ? TimeUnit.MILLISECONDS : iTimeUnit;
return new RetryOperation<>(
iRetryConsumer,
iNoOfRetry,
iDelayInterval,
iTimeUnit,
iRetryPredicate,
exceptionList,
message);
}
}
public static interface RetryConsumer {
T evaluate() throws Exception;
}
public static interface RetryPredicate {
boolean shouldRetry(T t);
}
}