@@ -74,9 +74,12 @@ public class TimeoutTest {
74
74
private static final int DEADLINE_IN_MINUTES = 10 ;
75
75
private static final int DEADLINE_IN_SECONDS = 20 ;
76
76
private static final ImmutableSet <StatusCode .Code > emptyRetryCodes = ImmutableSet .of ();
77
+ private static final ImmutableSet <StatusCode .Code > retryUnknownCode =
78
+ ImmutableSet .of (StatusCode .Code .UNKNOWN );
77
79
private static final Duration totalTimeout = Duration .ofDays (DEADLINE_IN_DAYS );
78
80
private static final Duration maxRpcTimeout = Duration .ofMinutes (DEADLINE_IN_MINUTES );
79
81
private static final Duration initialRpcTimeout = Duration .ofSeconds (DEADLINE_IN_SECONDS );
82
+ private static final GrpcCallContext defaultCallContext = GrpcCallContext .createDefault ();
80
83
81
84
@ Rule public MockitoRule mockitoRule = MockitoJUnit .rule ().strictness (Strictness .STRICT_STUBS );
82
85
@ Mock private Marshaller <String > stringMarshaller ;
@@ -97,7 +100,8 @@ public void testNonRetryUnarySettings() {
97
100
.setRpcTimeoutMultiplier (1.0 )
98
101
.setMaxRpcTimeout (maxRpcTimeout )
99
102
.build ();
100
- CallOptions callOptionsUsed = setupUnaryCallable (retrySettings );
103
+ CallOptions callOptionsUsed =
104
+ setupUnaryCallable (retrySettings , emptyRetryCodes , defaultCallContext );
101
105
102
106
// Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days.
103
107
assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
@@ -108,6 +112,46 @@ public void testNonRetryUnarySettings() {
108
112
assertThat (callOptionsUsed .getAuthority ()).isEqualTo (CALL_OPTIONS_AUTHORITY );
109
113
}
110
114
115
+ @ Test
116
+ public void testNonRetryUnarySettingsContextWithRetry () {
117
+ RetrySettings retrySettings =
118
+ RetrySettings .newBuilder ()
119
+ .setTotalTimeout (totalTimeout )
120
+ .setInitialRetryDelay (Duration .ZERO )
121
+ .setRetryDelayMultiplier (1.0 )
122
+ .setMaxRetryDelay (Duration .ZERO )
123
+ .setMaxAttempts (1 )
124
+ .setJittered (true )
125
+ .setInitialRpcTimeout (initialRpcTimeout )
126
+ .setRpcTimeoutMultiplier (1.0 )
127
+ .setMaxRpcTimeout (maxRpcTimeout )
128
+ .build ();
129
+ Duration newTimeout = Duration .ofSeconds (5 );
130
+ RetrySettings contextRetrySettings =
131
+ retrySettings
132
+ .toBuilder ()
133
+ .setInitialRpcTimeout (newTimeout )
134
+ .setMaxRpcTimeout (newTimeout )
135
+ .setMaxAttempts (3 )
136
+ .build ();
137
+ GrpcCallContext retryingContext =
138
+ defaultCallContext
139
+ .withRetrySettings (contextRetrySettings )
140
+ .withRetryableCodes (retryUnknownCode );
141
+ CallOptions callOptionsUsed =
142
+ setupUnaryCallable (retrySettings , emptyRetryCodes , retryingContext );
143
+
144
+ // Verify that the gRPC channel used the CallOptions the initial timeout of ~5 seconds.
145
+ // This indicates that the context retry settings were used on a callable that was instantiated
146
+ // with non-retryable settings.
147
+ assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
148
+ assertThat (callOptionsUsed .getDeadline ())
149
+ .isGreaterThan (Deadline .after (newTimeout .toSecondsPart () - 1 , TimeUnit .SECONDS ));
150
+ assertThat (callOptionsUsed .getDeadline ())
151
+ .isLessThan (Deadline .after (newTimeout .toSecondsPart (), TimeUnit .SECONDS ));
152
+ assertThat (callOptionsUsed .getAuthority ()).isEqualTo (CALL_OPTIONS_AUTHORITY );
153
+ }
154
+
111
155
@ Test
112
156
public void testNonRetryUnarySettingsWithoutInitialRpcTimeout () {
113
157
RetrySettings retrySettings =
@@ -121,7 +165,8 @@ public void testNonRetryUnarySettingsWithoutInitialRpcTimeout() {
121
165
.setRpcTimeoutMultiplier (1.0 )
122
166
.setMaxRpcTimeout (maxRpcTimeout )
123
167
.build ();
124
- CallOptions callOptionsUsed = setupUnaryCallable (retrySettings );
168
+ CallOptions callOptionsUsed =
169
+ setupUnaryCallable (retrySettings , emptyRetryCodes , defaultCallContext );
125
170
126
171
// Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days.
127
172
assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
@@ -145,7 +190,8 @@ public void testNonRetryUnarySettingsWithoutIndividualRpcTimeout() {
145
190
.setRpcTimeoutMultiplier (1.0 )
146
191
.setRpcTimeoutMultiplier (1.0 )
147
192
.build ();
148
- CallOptions callOptionsUsed = setupUnaryCallable (retrySettings );
193
+ CallOptions callOptionsUsed =
194
+ setupUnaryCallable (retrySettings , emptyRetryCodes , defaultCallContext );
149
195
150
196
// Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days.
151
197
assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
@@ -170,7 +216,8 @@ public void testNonRetryServerStreamingSettings() {
170
216
.setRpcTimeoutMultiplier (1.0 )
171
217
.setMaxRpcTimeout (maxRpcTimeout )
172
218
.build ();
173
- CallOptions callOptionsUsed = setupServerStreamingCallable (retrySettings );
219
+ CallOptions callOptionsUsed =
220
+ setupServerStreamingCallable (retrySettings , emptyRetryCodes , defaultCallContext );
174
221
175
222
// Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days.
176
223
assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
@@ -181,6 +228,41 @@ public void testNonRetryServerStreamingSettings() {
181
228
assertThat (callOptionsUsed .getAuthority ()).isEqualTo (CALL_OPTIONS_AUTHORITY );
182
229
}
183
230
231
+ @ Test
232
+ public void testNonRetryServerStreamingSettingsContextWithRetry () {
233
+ RetrySettings retrySettings =
234
+ RetrySettings .newBuilder ()
235
+ .setTotalTimeout (totalTimeout )
236
+ .setInitialRetryDelay (Duration .ZERO )
237
+ .setRetryDelayMultiplier (1.0 )
238
+ .setMaxRetryDelay (Duration .ZERO )
239
+ .setMaxAttempts (1 )
240
+ .setJittered (true )
241
+ .setInitialRpcTimeout (initialRpcTimeout )
242
+ .setRpcTimeoutMultiplier (1.0 )
243
+ .setMaxRpcTimeout (maxRpcTimeout )
244
+ .build ();
245
+ Duration newTimeout = Duration .ofSeconds (5 );
246
+ RetrySettings contextRetrySettings =
247
+ retrySettings .toBuilder ().setTotalTimeout (newTimeout ).setMaxAttempts (3 ).build ();
248
+ GrpcCallContext retryingContext =
249
+ defaultCallContext
250
+ .withRetrySettings (contextRetrySettings )
251
+ .withRetryableCodes (retryUnknownCode );
252
+ CallOptions callOptionsUsed =
253
+ setupServerStreamingCallable (retrySettings , emptyRetryCodes , retryingContext );
254
+
255
+ // Verify that the gRPC channel used the CallOptions the total timeout of ~5 seconds.
256
+ // This indicates that the context retry settings were used on a callable that was instantiated
257
+ // with non-retryable settings.
258
+ assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
259
+ assertThat (callOptionsUsed .getDeadline ())
260
+ .isGreaterThan (Deadline .after (newTimeout .toSecondsPart () - 1 , TimeUnit .SECONDS ));
261
+ assertThat (callOptionsUsed .getDeadline ())
262
+ .isLessThan (Deadline .after (newTimeout .toSecondsPart (), TimeUnit .SECONDS ));
263
+ assertThat (callOptionsUsed .getAuthority ()).isEqualTo (CALL_OPTIONS_AUTHORITY );
264
+ }
265
+
184
266
@ Test
185
267
public void testNonRetryServerStreamingSettingsWithoutInitialRpcTimeout () {
186
268
RetrySettings retrySettings =
@@ -194,7 +276,8 @@ public void testNonRetryServerStreamingSettingsWithoutInitialRpcTimeout() {
194
276
.setRpcTimeoutMultiplier (1.0 )
195
277
.setMaxRpcTimeout (maxRpcTimeout )
196
278
.build ();
197
- CallOptions callOptionsUsed = setupServerStreamingCallable (retrySettings );
279
+ CallOptions callOptionsUsed =
280
+ setupServerStreamingCallable (retrySettings , emptyRetryCodes , defaultCallContext );
198
281
199
282
// Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days.
200
283
assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
@@ -218,7 +301,8 @@ public void testNonRetryServerStreamingSettingsWithoutIndividualRpcTimeout() {
218
301
.setRpcTimeoutMultiplier (1.0 )
219
302
.setRpcTimeoutMultiplier (1.0 )
220
303
.build ();
221
- CallOptions callOptionsUsed = setupServerStreamingCallable (retrySettings );
304
+ CallOptions callOptionsUsed =
305
+ setupServerStreamingCallable (retrySettings , emptyRetryCodes , defaultCallContext );
222
306
223
307
// Verify that the gRPC channel used the CallOptions with our custom timeout of ~2 Days.
224
308
assertThat (callOptionsUsed .getDeadline ()).isNotNull ();
@@ -229,7 +313,10 @@ public void testNonRetryServerStreamingSettingsWithoutIndividualRpcTimeout() {
229
313
assertThat (callOptionsUsed .getAuthority ()).isEqualTo (CALL_OPTIONS_AUTHORITY );
230
314
}
231
315
232
- private CallOptions setupUnaryCallable (RetrySettings retrySettings ) {
316
+ private CallOptions setupUnaryCallable (
317
+ RetrySettings retrySettings ,
318
+ ImmutableSet <StatusCode .Code > retryableCodes ,
319
+ GrpcCallContext callContext ) {
233
320
MethodDescriptor <String , String > methodDescriptor =
234
321
MethodDescriptor .<String , String >newBuilder ()
235
322
.setSchemaDescriptor ("yaml" )
@@ -248,8 +335,8 @@ private CallOptions setupUnaryCallable(RetrySettings retrySettings) {
248
335
// Clobber the "authority" property with an identifier that allows us to trace
249
336
// the use of this CallOptions variable.
250
337
CallOptions spyCallOptions = CallOptions .DEFAULT .withAuthority ("RETRYING_TEST" );
251
- GrpcCallContext grpcCallContext =
252
- GrpcCallContext . createDefault () .withChannel (managedChannel ).withCallOptions (spyCallOptions );
338
+ GrpcCallContext context =
339
+ callContext .withChannel (managedChannel ).withCallOptions (spyCallOptions );
253
340
254
341
ArgumentCaptor <CallOptions > callOptionsArgumentCaptor =
255
342
ArgumentCaptor .forClass (CallOptions .class );
@@ -266,16 +353,16 @@ private CallOptions setupUnaryCallable(RetrySettings retrySettings) {
266
353
.setMethodDescriptor (methodDescriptor )
267
354
.setParamsExtractor (paramsExtractor )
268
355
.build ();
269
- UnaryCallSettings <String , String > nonRetriedCallSettings =
356
+ UnaryCallSettings <String , String > unaryCallSettings =
270
357
UnaryCallSettings .<String , String >newUnaryCallSettingsBuilder ()
271
358
.setRetrySettings (retrySettings )
272
- .setRetryableCodes (emptyRetryCodes )
359
+ .setRetryableCodes (retryableCodes )
273
360
.build ();
274
361
UnaryCallable <String , String > callable =
275
362
GrpcCallableFactory .createUnaryCallable (
276
363
grpcCallSettings ,
277
- nonRetriedCallSettings ,
278
- ClientContext .newBuilder ().setDefaultCallContext (grpcCallContext ).build ());
364
+ unaryCallSettings ,
365
+ ClientContext .newBuilder ().setDefaultCallContext (context ).build ());
279
366
280
367
try {
281
368
ApiFuture <String > future = callable .futureCall ("Is your refrigerator running?" );
@@ -287,7 +374,10 @@ private CallOptions setupUnaryCallable(RetrySettings retrySettings) {
287
374
return callOptionsArgumentCaptor .getValue ();
288
375
}
289
376
290
- private CallOptions setupServerStreamingCallable (RetrySettings retrySettings ) {
377
+ private CallOptions setupServerStreamingCallable (
378
+ RetrySettings retrySettings ,
379
+ ImmutableSet <StatusCode .Code > retryableCodes ,
380
+ GrpcCallContext callContext ) {
291
381
MethodDescriptor <String , String > methodDescriptor =
292
382
MethodDescriptor .<String , String >newBuilder ()
293
383
.setSchemaDescriptor ("yaml" )
@@ -306,8 +396,8 @@ private CallOptions setupServerStreamingCallable(RetrySettings retrySettings) {
306
396
// Clobber the "authority" property with an identifier that allows us to trace
307
397
// the use of this CallOptions variable.
308
398
CallOptions spyCallOptions = CallOptions .DEFAULT .withAuthority ("RETRYING_TEST" );
309
- GrpcCallContext grpcCallContext =
310
- GrpcCallContext . createDefault () .withChannel (managedChannel ).withCallOptions (spyCallOptions );
399
+ GrpcCallContext context =
400
+ callContext .withChannel (managedChannel ).withCallOptions (spyCallOptions );
311
401
312
402
ArgumentCaptor <CallOptions > callOptionsArgumentCaptor =
313
403
ArgumentCaptor .forClass (CallOptions .class );
@@ -324,16 +414,16 @@ private CallOptions setupServerStreamingCallable(RetrySettings retrySettings) {
324
414
.setMethodDescriptor (methodDescriptor )
325
415
.setParamsExtractor (paramsExtractor )
326
416
.build ();
327
- ServerStreamingCallSettings <String , String > nonRetriedCallSettings =
417
+ ServerStreamingCallSettings <String , String > serverStreamingCallSettings =
328
418
ServerStreamingCallSettings .<String , String >newBuilder ()
329
419
.setRetrySettings (retrySettings )
330
- .setRetryableCodes (emptyRetryCodes )
420
+ .setRetryableCodes (retryableCodes )
331
421
.build ();
332
422
ServerStreamingCallable <String , String > callable =
333
423
GrpcCallableFactory .createServerStreamingCallable (
334
424
grpcCallSettings ,
335
- nonRetriedCallSettings ,
336
- ClientContext .newBuilder ().setDefaultCallContext (grpcCallContext ).build ());
425
+ serverStreamingCallSettings ,
426
+ ClientContext .newBuilder ().setDefaultCallContext (context ).build ());
337
427
338
428
try {
339
429
ServerStream <String > stream = callable .call ("Is your refrigerator running?" );
0 commit comments