
org.ldaptive.handler.AbstractRetryOperationExceptionHandler Maven / Gradle / Ivy
/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.handler;
import java.util.concurrent.TimeUnit;
import org.ldaptive.Connection;
import org.ldaptive.LdapException;
import org.ldaptive.Request;
import org.ldaptive.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides common implementation for retrying after an operation exception.
*
* @param type of ldap request
* @param type of ldap response
*
* @author Middleware Services
*/
public abstract class AbstractRetryOperationExceptionHandler
implements OperationExceptionHandler
{
/** Logger for this class. */
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** Number of times to retry. */
private int retry;
/** Amount of time in seconds to wait before retries. */
private long retryWait;
/** Factor to multiply retry wait by. */
private int retryBackoff;
/**
* Returns the retry. This is the number of times the handler will retry when it fails.
*
* @return retry
*/
public int getRetry()
{
return retry;
}
/**
* Sets the number of retries.
*
* @param i to set
*/
public void setRetry(final int i)
{
logger.trace("setting retry: {}", i);
retry = i;
}
/**
* Returns the retry wait. This is the amount of time in seconds that the executing thread will sleep before
* attempting to retry again.
*
* @return retry wait
*/
public long getRetryWait()
{
return retryWait;
}
/**
* Sets the retry wait. Time must be >= 0.
*
* @param time in seconds
*/
public void setRetryWait(final long time)
{
if (time >= 0) {
logger.trace("setting retryWait: {}", time);
retryWait = time;
}
}
/**
* Returns the retry backoff. This is the factor by which the retry wait will be multiplied in order to progressively
* delay the amount of time between each retry.
*
* @return retry backoff
*/
public int getRetryBackoff()
{
return retryBackoff;
}
/**
* Sets the retry backoff.
*
* @param backoff to set
*/
public void setRetryBackoff(final int backoff)
{
logger.trace("setting retryBackoff: {}", backoff);
retryBackoff = backoff;
}
@Override
public HandlerResult> handle(final Connection conn, final Q request, final Response response)
throws LdapException
{
for (int i = 0; i <= retry || retry == -1; i++) {
try {
handleInternal(conn, request, response);
break;
} catch (LdapException e) {
logger.error("unable to handle operation exception", e);
if (!retry(i)) {
// handle failed, throw the original exception
return new HandlerResult<>(null, true);
}
}
}
return createResult(conn, request, response);
}
/**
* Perform any operations required to recover from the operation exception.
*
* @param conn connection the operation was executed on
* @param request executed by the operation
* @param response typically null
*
* @throws LdapException if the retry fails
*/
protected abstract void handleInternal(final Connection conn, final Q request, final Response response)
throws LdapException;
/**
* Invoked if {@link #handleInternal} succeeded. Creates a response for the original invocation that failed.
*
* @param conn connection the operation was executed on
* @param request executed by the operation
* @param response typically null
*
* @return handler result containing a response for the original invocation
*
* @throws LdapException if the operation fails
*/
protected abstract HandlerResult> createResult(
final Connection conn,
final Q request,
final Response response)
throws LdapException;
/**
* Returns whether the supplied count indicates that the operation should be retried. If a retry wait has been
* configured, this method will sleep the current thread for the configured time.
*
* @param count number of times the operation has been retried
*
* @return whether to retry
*/
protected boolean retry(final int count)
{
if (count < retry || retry == -1) {
logger.warn("Retry attempt {} of {}: wait={}, backoff={}", count + 1, retry, retryWait, retryBackoff);
if (retryWait > 0) {
long sleepTime = retryWait;
if (retryBackoff > 0 && count > 0) {
sleepTime = sleepTime * retryBackoff * count;
}
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(sleepTime));
} catch (InterruptedException ie) {
logger.debug("Retry wait interrupted", ie);
}
}
return true;
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy