@Override public boolean shouldRetry( AmazonWebServiceRequest originalRequest, AmazonClientException exception, int retriesAttempted) { // Always retry on client exceptions caused by IOException if (exception.getCause() instanceof IOException) return true; // Only retry on a subset of service exceptions if (exception instanceof AmazonServiceException) { AmazonServiceException ase = (AmazonServiceException) exception; /* * For 500 internal server errors and 503 service * unavailable errors, we want to retry, but we need to use * an exponential back-off strategy so that we don't overload * a server with a flood of retries. */ if (ase.getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR || ase.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE) { return true; } /* * Throttling is reported as a 400 error from newer services. To try * and smooth out an occasional throttling error, we'll pause and * retry, hoping that the pause is long enough for the request to * get through the next time. */ if (RetryUtils.isThrottlingException(ase)) return true; /* * Clock skew exception. If it is then we will get the time offset * between the device time and the server time to set the clock skew * and then retry the request. */ if (RetryUtils.isClockSkewError(ase)) return true; } return false; }
/** {@inheritDoc} */ @Override public final long delayBeforeNextRetry( AmazonWebServiceRequest originalRequest, AmazonClientException exception, int retriesAttempted) { if (retriesAttempted < 0) return 0; if (retriesAttempted > MAX_RETRIES_BEFORE_MAX_BACKOFF) return MAX_BACKOFF_IN_MILLISECONDS; int scaleFactor; if (exception instanceof AmazonServiceException && RetryUtils.isThrottlingException((AmazonServiceException) exception)) { scaleFactor = THROTTLING_SCALE_FACTOR + random.nextInt(THROTTLING_SCALE_FACTOR_RANDOM_RANGE); } else { scaleFactor = SCALE_FACTOR; } long delay = (1L << retriesAttempted) * scaleFactor; delay = Math.min(delay, MAX_BACKOFF_IN_MILLISECONDS); return delay; }