21
21
import com .linecorp .armeria .common .HttpResponse ;
22
22
import com .linecorp .armeria .common .HttpStatus ;
23
23
import com .linecorp .armeria .testing .junit5 .server .mock .MockWebServerExtension ;
24
+ import io .opentelemetry .sdk .common .export .DefaultRetryExceptionPredicate ;
24
25
import io .opentelemetry .sdk .common .export .RetryPolicy ;
25
26
import java .io .IOException ;
26
27
import java .net .ConnectException ;
29
30
import java .net .SocketTimeoutException ;
30
31
import java .time .Duration ;
31
32
import java .util .concurrent .TimeUnit ;
32
- import java .util .function .Function ;
33
+ import java .util .function .Predicate ;
33
34
import okhttp3 .OkHttpClient ;
34
35
import okhttp3 .Request ;
35
36
import okhttp3 .Response ;
@@ -49,34 +50,40 @@ class RetryInterceptorTest {
49
50
50
51
@ Mock private RetryInterceptor .Sleeper sleeper ;
51
52
@ Mock private RetryInterceptor .BoundedLongGenerator random ;
52
- private Function <IOException , Boolean > isRetryableException ;
53
+ private Predicate <IOException > retryPredicate ;
53
54
54
55
private RetryInterceptor retrier ;
55
56
private OkHttpClient client ;
56
57
57
58
@ BeforeEach
58
59
void setUp () {
59
- // Note: cannot replace this with lambda or method reference because we need to spy on it
60
- isRetryableException =
60
+ DefaultRetryExceptionPredicate defaultRetryExceptionPredicate =
61
+ new DefaultRetryExceptionPredicate ();
62
+ retryPredicate =
61
63
spy (
62
- new Function <IOException , Boolean >() {
64
+ new Predicate <IOException >() {
63
65
@ Override
64
- public Boolean apply (IOException exception ) {
65
- return RetryInterceptor . isRetryableException ( exception )
66
- || (exception instanceof HttpRetryException
67
- && exception .getMessage ().contains ("timeout retry" ));
66
+ public boolean test (IOException e ) {
67
+ return defaultRetryExceptionPredicate . test ( e )
68
+ || (e instanceof HttpRetryException
69
+ && e .getMessage ().contains ("timeout retry" ));
68
70
}
69
71
});
72
+
73
+ RetryPolicy retryPolicy =
74
+ RetryPolicy .builder ()
75
+ .setBackoffMultiplier (1.6 )
76
+ .setInitialBackoff (Duration .ofSeconds (1 ))
77
+ .setMaxBackoff (Duration .ofSeconds (2 ))
78
+ .setMaxAttempts (5 )
79
+ .setRetryExceptionPredicate (retryPredicate )
80
+ .build ();
81
+
70
82
retrier =
71
83
new RetryInterceptor (
72
- RetryPolicy .builder ()
73
- .setBackoffMultiplier (1.6 )
74
- .setInitialBackoff (Duration .ofSeconds (1 ))
75
- .setMaxBackoff (Duration .ofSeconds (2 ))
76
- .setMaxAttempts (5 )
77
- .build (),
84
+ retryPolicy ,
78
85
r -> !r .isSuccessful (),
79
- isRetryableException ,
86
+ e -> retryPolicy . getRetryExceptionPredicate (). test ( e ) ,
80
87
sleeper ,
81
88
random );
82
89
client = new OkHttpClient .Builder ().addInterceptor (retrier ).build ();
@@ -157,7 +164,7 @@ void connectTimeout() throws Exception {
157
164
client .newCall (new Request .Builder ().url ("http://10.255.255.1" ).build ()).execute ())
158
165
.isInstanceOf (SocketTimeoutException .class );
159
166
160
- verify (isRetryableException , times (5 )).apply (any ());
167
+ verify (retryPredicate , times (5 )).test (any ());
161
168
// Should retry maxAttempts, and sleep maxAttempts - 1 times
162
169
verify (sleeper , times (4 )).sleep (anyLong ());
163
170
}
@@ -177,7 +184,7 @@ void connectException() throws Exception {
177
184
.execute ())
178
185
.isInstanceOfAny (ConnectException .class , SocketTimeoutException .class );
179
186
180
- verify (isRetryableException , times (5 )).apply (any ());
187
+ verify (retryPredicate , times (5 )).test (any ());
181
188
// Should retry maxAttempts, and sleep maxAttempts - 1 times
182
189
verify (sleeper , times (4 )).sleep (anyLong ());
183
190
}
@@ -193,16 +200,16 @@ private static int freePort() {
193
200
@ Test
194
201
void nonRetryableException () throws InterruptedException {
195
202
client = connectTimeoutClient ();
196
- // Override isRetryableException so that no exception is retryable
197
- when (isRetryableException . apply (any ())).thenReturn (false );
203
+ // Override retryPredicate so that no exception is retryable
204
+ when (retryPredicate . test (any ())).thenReturn (false );
198
205
199
206
// Connecting to a non-routable IP address to trigger connection timeout
200
207
assertThatThrownBy (
201
208
() ->
202
209
client .newCall (new Request .Builder ().url ("http://10.255.255.1" ).build ()).execute ())
203
210
.isInstanceOf (SocketTimeoutException .class );
204
211
205
- verify (isRetryableException , times (1 )).apply (any ());
212
+ verify (retryPredicate , times (1 )).test (any ());
206
213
verify (sleeper , never ()).sleep (anyLong ());
207
214
}
208
215
@@ -224,8 +231,8 @@ void isRetryableException() {
224
231
// Shouldn't retry on read timeouts, where error message is "Read timed out"
225
232
assertThat (retrier .shouldRetryOnException (new SocketTimeoutException ("Read timed out" )))
226
233
.isFalse ();
227
- // Shouldn't retry on write timeouts, where error message is "timeout", or other IOException
228
- assertThat (retrier .shouldRetryOnException (new SocketTimeoutException ("timeout" ))).isFalse ();
234
+ // Shouldn't retry on write timeouts or other IOException
235
+ assertThat (retrier .shouldRetryOnException (new SocketTimeoutException ("timeout" ))).isTrue ();
229
236
assertThat (retrier .shouldRetryOnException (new SocketTimeoutException ())).isTrue ();
230
237
assertThat (retrier .shouldRetryOnException (new IOException ("error" ))).isFalse ();
231
238
@@ -261,7 +268,7 @@ void isRetryableExceptionCustomRetryPredicate() {
261
268
assertThat (
262
269
retryInterceptor .shouldRetryOnException (
263
270
new SocketTimeoutException ("Connect timed out" )))
264
- .isTrue ();
271
+ .isFalse ();
265
272
}
266
273
267
274
private Response sendRequest () throws IOException {
0 commit comments