29
29
import com .google .common .base .Stopwatch ;
30
30
31
31
import java .io .InterruptedIOException ;
32
+ import java .net .SocketTimeoutException ;
32
33
import java .nio .channels .ClosedByInterruptException ;
33
34
import java .util .concurrent .Callable ;
34
35
import java .util .logging .Level ;
44
45
public class RetryHelper <V > {
45
46
46
47
private static final Logger log = Logger .getLogger (RetryHelper .class .getName ());
48
+ private final static boolean DEFAULT_RETRY_ON_TIMEOUTS = true ;
47
49
48
50
private final Stopwatch stopwatch ;
49
51
private final Callable <V > callable ;
50
52
private final RetryParams params ;
51
53
private final ExceptionHandler exceptionHandler ;
52
54
private int attemptNumber ;
53
55
54
-
55
56
private static final ThreadLocal <Context > context = new ThreadLocal <>();
56
57
57
58
public static class RetryHelperException extends RuntimeException {
@@ -172,7 +173,7 @@ public String toString() {
172
173
return toStringHelper .toString ();
173
174
}
174
175
175
- private V doRetry () throws RetryHelperException {
176
+ private V doRetry (boolean retryOnTimeout ) throws RetryHelperException {
176
177
stopwatch .start ();
177
178
while (true ) {
178
179
attemptNumber ++;
@@ -189,7 +190,8 @@ private V doRetry() throws RetryHelperException {
189
190
}
190
191
exception = e ;
191
192
} catch (Exception e ) {
192
- if (!exceptionHandler .shouldRetry (e )) {
193
+ if (!exceptionHandler .shouldRetry (e )
194
+ || !retryOnTimeout && e .getCause () instanceof SocketTimeoutException ) {
193
195
throw new NonRetriableException (e );
194
196
}
195
197
exception = e ;
@@ -229,22 +231,30 @@ private static long getExponentialValue(long initialDelay, double backoffFactor,
229
231
230
232
public static <V > V runWithRetries (Callable <V > callable ) throws RetryHelperException {
231
233
return runWithRetries (callable , RetryParams .defaultInstance (),
232
- ExceptionHandler .defaultInstance ());
234
+ ExceptionHandler .defaultInstance (), DEFAULT_RETRY_ON_TIMEOUTS );
233
235
}
234
236
235
237
public static <V > V runWithRetries (Callable <V > callable , RetryParams params ,
236
238
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 );
238
247
}
239
248
240
249
@ VisibleForTesting
241
250
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 {
243
253
RetryHelper <V > retryHelper = new RetryHelper <>(callable , params , exceptionHandler , stopwatch );
244
254
Context previousContext = getContext ();
245
255
setContext (new Context (retryHelper ));
246
256
try {
247
- return retryHelper .doRetry ();
257
+ return retryHelper .doRetry (retryOnTimeout );
248
258
} finally {
249
259
setContext (previousContext );
250
260
}
0 commit comments