2929import com .google .common .base .Stopwatch ;
3030
3131import java .io .InterruptedIOException ;
32+ import java .net .SocketTimeoutException ;
3233import java .nio .channels .ClosedByInterruptException ;
3334import java .util .concurrent .Callable ;
3435import java .util .logging .Level ;
4445public class RetryHelper <V > {
4546
4647 private static final Logger log = Logger .getLogger (RetryHelper .class .getName ());
48+ private final static boolean DEFAULT_RETRY_ON_TIMEOUTS = true ;
4749
4850 private final Stopwatch stopwatch ;
4951 private final Callable <V > callable ;
5052 private final RetryParams params ;
5153 private final ExceptionHandler exceptionHandler ;
5254 private int attemptNumber ;
5355
54-
5556 private static final ThreadLocal <Context > context = new ThreadLocal <>();
5657
5758 public static class RetryHelperException extends RuntimeException {
@@ -172,7 +173,7 @@ public String toString() {
172173 return toStringHelper .toString ();
173174 }
174175
175- private V doRetry () throws RetryHelperException {
176+ private V doRetry (boolean retryOnTimeout ) throws RetryHelperException {
176177 stopwatch .start ();
177178 while (true ) {
178179 attemptNumber ++;
@@ -189,7 +190,8 @@ private V doRetry() throws RetryHelperException {
189190 }
190191 exception = e ;
191192 } catch (Exception e ) {
192- if (!exceptionHandler .shouldRetry (e )) {
193+ if (!exceptionHandler .shouldRetry (e )
194+ || !retryOnTimeout && e .getCause () instanceof SocketTimeoutException ) {
193195 throw new NonRetriableException (e );
194196 }
195197 exception = e ;
@@ -229,22 +231,30 @@ private static long getExponentialValue(long initialDelay, double backoffFactor,
229231
230232 public static <V > V runWithRetries (Callable <V > callable ) throws RetryHelperException {
231233 return runWithRetries (callable , RetryParams .defaultInstance (),
232- ExceptionHandler .defaultInstance ());
234+ ExceptionHandler .defaultInstance (), DEFAULT_RETRY_ON_TIMEOUTS );
233235 }
234236
235237 public static <V > V runWithRetries (Callable <V > callable , RetryParams params ,
236238 ExceptionHandler exceptionHandler ) throws RetryHelperException {
237- return runWithRetries (callable , params , exceptionHandler , Stopwatch .createUnstarted ());
239+ return runWithRetries (callable , params , exceptionHandler , Stopwatch .createUnstarted (),
240+ DEFAULT_RETRY_ON_TIMEOUTS );
241+ }
242+
243+ public static <V > V runWithRetries (Callable <V > callable , RetryParams params ,
244+ ExceptionHandler exceptionHandler , boolean retryOnTimeout ) throws RetryHelperException {
245+ return runWithRetries (callable , params , exceptionHandler , Stopwatch .createUnstarted (),
246+ retryOnTimeout );
238247 }
239248
240249 @ VisibleForTesting
241250 static <V > V runWithRetries (Callable <V > callable , RetryParams params ,
242- ExceptionHandler exceptionHandler , Stopwatch stopwatch ) throws RetryHelperException {
251+ ExceptionHandler exceptionHandler , Stopwatch stopwatch , boolean retryOnTimeout )
252+ throws RetryHelperException {
243253 RetryHelper <V > retryHelper = new RetryHelper <>(callable , params , exceptionHandler , stopwatch );
244254 Context previousContext = getContext ();
245255 setContext (new Context (retryHelper ));
246256 try {
247- return retryHelper .doRetry ();
257+ return retryHelper .doRetry (retryOnTimeout );
248258 } finally {
249259 setContext (previousContext );
250260 }
0 commit comments