Skip to content

Commit 6be4b7c

Browse files
committed
Avoid multiple picker updates when resetting backoffs when RLS control plane transitions to READY.
1 parent a0c7c94 commit 6be4b7c

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,18 @@ public void run() {
226226
} else if (wasInTransientFailure && currentState == ConnectivityState.READY) {
227227
wasInTransientFailure = false;
228228
synchronized (lock) {
229+
boolean anyBackoffsCanceled = false;
229230
for (CacheEntry value : linkedHashLruCache.values()) {
230231
if (value instanceof BackoffCacheEntry) {
231-
refreshBackoffEntry((BackoffCacheEntry) value);
232+
if (((BackoffCacheEntry) value).scheduledFuture.cancel(false)) {
233+
anyBackoffsCanceled = true;
234+
}
232235
}
233236
}
237+
if (anyBackoffsCanceled) {
238+
// Cache updated. updateBalancingState() to reattempt picks
239+
helper.triggerPendingRpcProcessing();
240+
}
234241
}
235242
}
236243
rlsChannel.notifyWhenStateChanged(currentState, this);

rls/src/test/java/io/grpc/rls/CachingRlsLbClientTest.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -484,12 +484,18 @@ public void run() {
484484
fakeThrottler.nextResult = true;
485485
fakeBackoffProvider.nextPolicy = createBackoffPolicy(10, TimeUnit.MILLISECONDS);
486486

487-
// Cause a cache miss by using a new request key. This will create a back-off Rls cache entry.
487+
// Cause two cache misses by using new request keys. This will create back-off Rls cache
488+
// entries. RLS control plane state transitioning to READY should reset both back-offs but
489+
// update picker only once.
488490
RlsProtoData.RouteLookupRequestKey routeLookupRequestKey2 =
489491
RlsProtoData.RouteLookupRequestKey.create(ImmutableMap.of(
490492
"server", "bigtable.googleapis.com", "service-key", "foo2", "method-key", "bar"));
491493
resp = getInSyncContext(routeLookupRequestKey2);
492-
494+
assertThat(resp.hasError()).isTrue();
495+
RlsProtoData.RouteLookupRequestKey routeLookupRequestKey3 =
496+
RlsProtoData.RouteLookupRequestKey.create(ImmutableMap.of(
497+
"server", "bigtable.googleapis.com", "service-key", "foo3", "method-key", "bar"));
498+
resp = getInSyncContext(routeLookupRequestKey3);
493499
assertThat(resp.hasError()).isTrue();
494500

495501
fakeHelper.createServerAndRegister("service1");
@@ -508,20 +514,24 @@ public void run() {
508514
ArgumentCaptor<ConnectivityState> stateCaptor =
509515
ArgumentCaptor.forClass(ConnectivityState.class);
510516

511-
inOrder.verify(helper, times(5))
517+
inOrder.verify(helper, times(4))
512518
.updateBalancingState(stateCaptor.capture(), pickerCaptor.capture());
513519
assertThat(new HashSet<>(pickerCaptor.getAllValues())).hasSize(1);
514520
assertThat(stateCaptor.getAllValues())
515521
.containsExactly(ConnectivityState.TRANSIENT_FAILURE, ConnectivityState.CONNECTING,
516-
ConnectivityState.CONNECTING, ConnectivityState.CONNECTING,
517-
ConnectivityState.CONNECTING);
522+
ConnectivityState.CONNECTING, ConnectivityState.CONNECTING);
518523
Metadata headers = new Metadata();
519524
PickResult pickResult = getPickResultForCreate(pickerCaptor, headers);
520525
assertThat(pickResult.getStatus().getCode()).isEqualTo(Status.Code.UNAVAILABLE);
521526
assertThat(pickResult.getStatus().getDescription()).isEqualTo("fallback not available");
522527
isSuccess.set(true);
523528
}).get();
524529
assertThat(isSuccess.get()).isTrue();
530+
531+
fakeThrottler.nextResult = false;
532+
// Rpcs are not backed off now.
533+
assertThat(getInSyncContext(routeLookupRequestKey2).isPending()).isTrue();
534+
assertThat(getInSyncContext(routeLookupRequestKey3).isPending()).isTrue();
525535
}
526536

527537
@Test

0 commit comments

Comments
 (0)