diff --git a/core/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java b/core/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java index 66380b9631bb..922cd5e3925a 100644 --- a/core/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java +++ b/core/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java @@ -310,9 +310,9 @@ void clearAddressTracker() { } void eject() { - ejected = true; subchannelStateListener.onSubchannelState( ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE)); + ejected = true; } void uneject() { diff --git a/core/src/test/java/io/grpc/util/OutlierDetectionLoadBalancerTest.java b/core/src/test/java/io/grpc/util/OutlierDetectionLoadBalancerTest.java index 5b73edb4c2c5..66ba5048535e 100644 --- a/core/src/test/java/io/grpc/util/OutlierDetectionLoadBalancerTest.java +++ b/core/src/test/java/io/grpc/util/OutlierDetectionLoadBalancerTest.java @@ -354,7 +354,7 @@ public void successRateNoOutliers() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of()); + generateLoad(ImmutableMap.of(), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -378,7 +378,7 @@ public void successRateOneOutlier() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -403,7 +403,7 @@ public void successRateOneOutlier_configChange() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -423,7 +423,7 @@ public void successRateOneOutlier_configChange() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel2, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel2, Status.DEADLINE_EXCEEDED), 8); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -448,7 +448,7 @@ public void successRateOneOutlier_unejected() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. fakeClock.forwardTime(config.intervalNanos + 1, TimeUnit.NANOSECONDS); @@ -457,7 +457,7 @@ public void successRateOneOutlier_unejected() { assertEjectedSubchannels(ImmutableSet.of(servers.get(0).getAddresses().get(0))); // Now we produce more load, but the subchannel start working and is no longer an outlier. - generateLoad(ImmutableMap.of()); + generateLoad(ImmutableMap.of(), 8); // Move forward in time to a point where the detection timer has fired. fakeClock.forwardTime(config.maxEjectionTimeNanos + 1, TimeUnit.NANOSECONDS); @@ -484,7 +484,7 @@ public void successRateOneOutlier_notEnoughVolume() { // We produce an outlier, but don't give it enough calls to reach the minimum volume. generateLoad( ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), - ImmutableMap.of(subchannel1, 19)); + ImmutableMap.of(subchannel1, 19), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -508,7 +508,7 @@ public void successRateOneOutlier_notEnoughAddressesWithVolume() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -534,7 +534,7 @@ public void successRateOneOutlier_enforcementPercentage() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -561,7 +561,7 @@ public void successRateTwoOutliers() { generateLoad(ImmutableMap.of( subchannel1, Status.DEADLINE_EXCEEDED, - subchannel2, Status.DEADLINE_EXCEEDED)); + subchannel2, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -589,7 +589,7 @@ public void successRateTwoOutliers_maxEjectionPercentage() { generateLoad(ImmutableMap.of( subchannel1, Status.DEADLINE_EXCEEDED, - subchannel2, Status.DEADLINE_EXCEEDED)); + subchannel2, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -624,7 +624,7 @@ public void failurePercentageNoOutliers() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); // By default all calls will return OK. - generateLoad(ImmutableMap.of()); + generateLoad(ImmutableMap.of(), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -648,7 +648,7 @@ public void failurePercentageOneOutlier() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -672,7 +672,7 @@ public void failurePercentageOneOutlier_notEnoughVolume() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -698,7 +698,7 @@ public void failurePercentageOneOutlier_enforcementPercentage() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -735,7 +735,7 @@ public void successRateAndFailurePercentageThreeOutliers() { subchannel1, Status.DEADLINE_EXCEEDED, subchannel2, Status.DEADLINE_EXCEEDED, subchannel3, Status.DEADLINE_EXCEEDED), - ImmutableMap.of(subchannel3, 1)); + ImmutableMap.of(subchannel3, 1), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -764,7 +764,7 @@ public void subchannelUpdateAddress_singleReplaced() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -811,7 +811,7 @@ public void subchannelUpdateAddress_singleReplacedWithMultiple() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of()); + generateLoad(ImmutableMap.of(), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -858,7 +858,7 @@ public void subchannelUpdateAddress_multipleReplacedWithSingle() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -920,7 +920,7 @@ public void successRateAndFailurePercentage_noOutliers() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of()); + generateLoad(ImmutableMap.of(), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -947,7 +947,7 @@ public void successRateAndFailurePercentage_successRateOutlier() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -974,7 +974,7 @@ public void successRateAndFailurePercentage_errorPercentageOutlier() { loadBalancer.handleResolvedAddresses(buildResolvedAddress(config, servers)); - generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED)); + generateLoad(ImmutableMap.of(subchannel1, Status.DEADLINE_EXCEEDED), 7); // Move forward in time to a point where the detection timer has fired. forwardTime(config); @@ -1023,22 +1023,23 @@ private void deliverSubchannelState(Subchannel subchannel, ConnectivityStateInfo subchannelStateListeners.get(subchannel).onSubchannelState(newState); } - private void generateLoad(Map statusMap) { - generateLoad(statusMap, null); + private void generateLoad(Map statusMap, int expectedStateChanges) { + generateLoad(statusMap, null, expectedStateChanges); } // Generates 100 calls, 20 each across the subchannels. Default status is OK. private void generateLoad(Map statusMap, - Map maxCallsMap) { + Map maxCallsMap, int expectedStateChanges) { deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(READY)); deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(READY)); deliverSubchannelState(subchannel3, ConnectivityStateInfo.forNonError(READY)); deliverSubchannelState(subchannel4, ConnectivityStateInfo.forNonError(READY)); deliverSubchannelState(subchannel5, ConnectivityStateInfo.forNonError(READY)); - verify(mockHelper, times(7)).updateBalancingState(stateCaptor.capture(), + verify(mockHelper, times(expectedStateChanges)).updateBalancingState(stateCaptor.capture(), pickerCaptor.capture()); - SubchannelPicker picker = pickerCaptor.getAllValues().get(6); + SubchannelPicker picker = pickerCaptor.getAllValues() + .get(pickerCaptor.getAllValues().size() - 1); HashMap callCountMap = new HashMap<>(); for (int i = 0; i < 100; i++) {