23
23
import com .google .api .gax .grpc .InstantiatingExecutorProvider ;
24
24
import com .google .auth .Credentials ;
25
25
import com .google .auth .oauth2 .GoogleCredentials ;
26
+ import com .google .common .annotations .VisibleForTesting ;
26
27
import com .google .common .base .Optional ;
27
28
import com .google .common .base .Preconditions ;
28
29
import com .google .common .collect .ImmutableList ;
@@ -125,6 +126,7 @@ public static long getApiMaxRequestBytes() {
125
126
126
127
private final BundlingSettings bundlingSettings ;
127
128
private final RetrySettings retrySettings ;
129
+ private final LongRandom longRandom ;
128
130
129
131
private final FlowController .Settings flowControlSettings ;
130
132
private final boolean failOnFlowControlLimits ;
@@ -151,6 +153,7 @@ private Publisher(Builder builder) throws IOException {
151
153
152
154
this .bundlingSettings = builder .bundlingSettings ;
153
155
this .retrySettings = builder .retrySettings ;
156
+ this .longRandom = builder .longRandom ;
154
157
155
158
flowControlSettings = builder .flowControlSettings ;
156
159
failOnFlowControlLimits = builder .failOnFlowControlLimits ;
@@ -380,7 +383,8 @@ public void onSuccess(PublishResponse result) {
380
383
381
384
@ Override
382
385
public void onFailure (Throwable t ) {
383
- long nextBackoffDelay = computeNextBackoffDelayMs (outstandingBundle , retrySettings );
386
+ long nextBackoffDelay =
387
+ computeNextBackoffDelayMs (outstandingBundle , retrySettings , longRandom );
384
388
385
389
if (!isRetryable (t )
386
390
|| System .currentTimeMillis () + nextBackoffDelay
@@ -494,14 +498,14 @@ private boolean hasBundlingBytes() {
494
498
}
495
499
496
500
private static long computeNextBackoffDelayMs (
497
- OutstandingBundle outstandingBundle , RetrySettings retrySettings ) {
501
+ OutstandingBundle outstandingBundle , RetrySettings retrySettings , LongRandom longRandom ) {
498
502
long delayMillis =
499
503
Math .round (
500
504
retrySettings .getInitialRetryDelay ().getMillis ()
501
505
* Math .pow (retrySettings .getRetryDelayMultiplier (), outstandingBundle .attempt - 1 ));
502
506
delayMillis = Math .min (retrySettings .getMaxRetryDelay ().getMillis (), delayMillis );
503
507
outstandingBundle .attempt ++;
504
- return ThreadLocalRandom . current (). nextLong (delayMillis / 2 , delayMillis );
508
+ return longRandom . nextLong (0 , delayMillis );
505
509
}
506
510
507
511
private boolean isRetryable (Throwable t ) {
@@ -520,6 +524,10 @@ private boolean isRetryable(Throwable t) {
520
524
}
521
525
}
522
526
527
+ interface LongRandom {
528
+ long nextLong (long least , long bound );
529
+ }
530
+
523
531
/** A builder of {@link Publisher}s. */
524
532
public static final class Builder {
525
533
static final Duration MIN_TOTAL_TIMEOUT = new Duration (10 * 1000 ); // 10 seconds
@@ -547,6 +555,13 @@ public static final class Builder {
547
555
.setRpcTimeoutMultiplier (2 )
548
556
.setMaxRpcTimeout (DEFAULT_RPC_TIMEOUT )
549
557
.build ();
558
+ static final LongRandom DEFAULT_LONG_RANDOM =
559
+ new LongRandom () {
560
+ @ Override
561
+ public long nextLong (long least , long bound ) {
562
+ return ThreadLocalRandom .current ().nextLong (least , bound );
563
+ }
564
+ };
550
565
551
566
private static final int THREADS_PER_CPU = 5 ;
552
567
static final ExecutorProvider DEFAULT_EXECUTOR_PROVIDER =
@@ -564,6 +579,7 @@ public static final class Builder {
564
579
boolean failOnFlowControlLimits = false ;
565
580
566
581
RetrySettings retrySettings = DEFAULT_RETRY_SETTINGS ;
582
+ LongRandom longRandom = DEFAULT_LONG_RANDOM ;
567
583
568
584
// Channels and credentials
569
585
Optional <Credentials > userCredentials = Optional .absent ();
@@ -659,6 +675,12 @@ public Builder setRetrySettings(RetrySettings retrySettings) {
659
675
return this ;
660
676
}
661
677
678
+ @ VisibleForTesting
679
+ Builder setLongRandom (LongRandom longRandom ) {
680
+ this .longRandom = Preconditions .checkNotNull (longRandom );
681
+ return this ;
682
+ }
683
+
662
684
/** Gives the ability to set a custom executor to be used by the library. */
663
685
public Builder setExecutorProvider (ExecutorProvider executorProvider ) {
664
686
this .executorProvider = Preconditions .checkNotNull (executorProvider );
0 commit comments