package org.springframework.data.simpledb.core; import com.amazonaws.AmazonClientException; import com.amazonaws.AmazonServiceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.data.simpledb.exception.SimpleDbExceptionTranslator; /** * Enables callbacks on execute() */ public abstract class AbstractServiceUnavailableOperationRetrier { private int serviceUnavailableRetries; public AbstractServiceUnavailableOperationRetrier(int serviceUnavailableRetries) { this.serviceUnavailableRetries = serviceUnavailableRetries; } private static final int RETRY_TIME = 400; private int currentRetry = 0; private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSimpleDbTemplate.class); public static final int SERVICE_UNAVAILABLE_STATUS_CODE = 503; /** * Override this method for specific operations that need retry for Amazon ServiceUnavailableException */ public abstract void execute(); public final void executeWithRetries() { try { AmazonClientException serviceUnavailableException = null; serviceUnavailableException = tryExecute(); while ((serviceUnavailableException != null) && currentRetry < serviceUnavailableRetries) { try { Thread.sleep(RETRY_TIME); } catch (InterruptedException e) { LOGGER.debug(e.getLocalizedMessage()); } LOGGER.debug("Retrying operation"); currentRetry++; serviceUnavailableException = tryExecute(); } if (currentRetry == serviceUnavailableRetries) { throw new DataAccessResourceFailureException( "SimpleDB operation failed for " + currentRetry + " times", serviceUnavailableException); } } catch (AmazonClientException exception) { throw SimpleDbExceptionTranslator.getTranslatorInstance().translateAmazonClientException(exception); } } /** * @return recognized exception or null, throws further not recognized exception */ private AmazonClientException tryExecute() { try { execute(); } catch (AmazonClientException clientException) { if (isServiceUnavailableException(clientException)) { return clientException; } throw clientException; } return null; } private boolean isServiceUnavailableException(AmazonClientException e) { return (((AmazonServiceException) e).getErrorType() == AmazonServiceException.ErrorType.Service && ((AmazonServiceException) e).getStatusCode() == AbstractServiceUnavailableOperationRetrier.SERVICE_UNAVAILABLE_STATUS_CODE); } public int getCurrentRetry() { return currentRetry; } }