/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.sa.service.aix.tasks;
import org.apache.commons.lang.StringUtils;
import com.iwave.ext.command.CommandException;
/**
* The RetryableCommandTask retries an AixExecutionTask up to a default of five times. Subclasses are responsible
* for implementing canRetry for thrown CommandExceptions
*
* @author Jay Logelin
*
* @param <T> the result Type
* @param <E> the Exception Type with which to check retry capabilities
*/
public abstract class RetryableCommandTask<T, E extends CommandException> extends AixExecutionTask<T> {
private static final int DEFAULT_MAX_TRIES = 5;
private static final long DEFAULT_DELAY = 10000;
private int maxTries = DEFAULT_MAX_TRIES;
private long delay = DEFAULT_DELAY;
private T result;
public int getMaxTries() {
return maxTries;
}
public void setMaxTries(int maxTries) {
this.maxTries = maxTries;
}
public long getDelay() {
return delay;
}
public void setDelay(long delay) {
this.delay = delay;
}
@Override
public T executeTask() throws Exception {
debug("Executing: %s", getDetail());
int tries = 1;
boolean success = tryOnce(tries);
while (!success) {
tries++;
Thread.sleep(delay);
logInfo("retryable.task", getName());
success = tryOnce(tries);
}
return result;
}
@SuppressWarnings("unchecked")
private boolean tryOnce(int tries) {
try {
result = tryExecute();
return true;
} catch (CommandException e) {
if (!canRetry((E) e)) {
fail((E) e);
}
else if (tries >= maxTries) {
logError("retryable.task.max.retries", getName());
fail((E) e);
}
String message = getMessage((E) e);
logInfo("retryable.task.failed.retry", getName(), message);
return false;
}
}
protected abstract T tryExecute();
protected abstract boolean canRetry(E e);
protected void fail(E e) {
String message = getMessage(e);
logError("retryable.task.failed.with.error", getName(), message);
throw e;
}
protected String getMessage(E e) {
String message = null;
String defaultMessage = null;
Throwable cause = e.getCause();
if (cause != null) {
message = cause.getMessage();
defaultMessage = cause.getClass().getName();
}
else {
message = e.getMessage();
defaultMessage = e.getClass().getName();
}
return StringUtils.defaultIfBlank(message, defaultMessage);
}
}