Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit c77e876

Browse files
committed
fix: pr feedback
Change-Id: Ic5f18450c5f60bcf5473e6890b41b006821ddf9d
1 parent e6cab0c commit c77e876

7 files changed

Lines changed: 59 additions & 31 deletions

File tree

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/BigtableChannelPrimer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.stub;
1717

18+
import com.google.api.core.ApiFuture;
1819
import com.google.api.core.InternalApi;
1920
import com.google.api.core.SettableApiFuture;
2021
import com.google.auth.Credentials;
@@ -110,8 +111,7 @@ private void sendPrimeRequestsBlocking(ManagedChannel managedChannel) {
110111
}
111112
}
112113

113-
public SettableApiFuture<PingAndWarmResponse> sendPrimeRequestsAsync(
114-
ManagedChannel managedChannel) {
114+
public ApiFuture<PingAndWarmResponse> sendPrimeRequestsAsync(ManagedChannel managedChannel) {
115115
ClientCall<PingAndWarmRequest, PingAndWarmResponse> clientCall =
116116
managedChannel.newCall(
117117
BigtableGrpc.getPingAndWarmMethod(),

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/NoOpChannelPrimer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.stub;
1717

18+
import com.google.api.core.ApiFuture;
1819
import com.google.api.core.InternalApi;
1920
import com.google.api.core.SettableApiFuture;
2021
import com.google.bigtable.v2.PingAndWarmResponse;
@@ -35,7 +36,7 @@ public void primeChannel(ManagedChannel channel) {
3536
}
3637

3738
@Override
38-
public SettableApiFuture<PingAndWarmResponse> sendPrimeRequestsAsync(ManagedChannel channel) {
39+
public ApiFuture<PingAndWarmResponse> sendPrimeRequestsAsync(ManagedChannel channel) {
3940
SettableApiFuture future = SettableApiFuture.create();
4041
future.set(PingAndWarmResponse.getDefaultInstance());
4142
return future;

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/grpc/BigtableChannelPool.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public static BigtableChannelPool create(
100100
this.channelPrimer = channelPrimer;
101101
Clock systemClock = Clock.systemUTC();
102102
this.channelPoolHealthChecker =
103-
new ChannelPoolHealthChecker(() -> entries.get(), channelPrimer, executor, systemClock);
103+
new ChannelPoolHealthChecker(entries::get, channelPrimer, executor, systemClock);
104104
this.channelPoolHealthChecker.start();
105105

106106
ImmutableList.Builder<Entry> initialListBuilder = ImmutableList.builder();

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/grpc/ChannelPoolHealthChecker.java

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,34 @@
1515
*/
1616
package com.google.cloud.bigtable.gaxx.grpc;
1717

18-
import com.google.api.core.SettableApiFuture;
18+
import com.google.api.core.ApiFuture;
1919
import com.google.auto.value.AutoValue;
2020
import com.google.bigtable.v2.PingAndWarmResponse;
2121
import com.google.cloud.bigtable.data.v2.stub.BigtableChannelPrimer;
2222
import com.google.cloud.bigtable.gaxx.grpc.BigtableChannelPool.Entry;
2323
import com.google.common.annotations.VisibleForTesting;
2424
import com.google.common.collect.ImmutableList;
25+
import com.google.common.util.concurrent.MoreExecutors;
2526
import java.time.Clock;
2627
import java.time.Duration;
2728
import java.time.Instant;
2829
import java.util.Comparator;
2930
import java.util.List;
3031
import java.util.concurrent.ScheduledExecutorService;
32+
import java.util.concurrent.ScheduledFuture;
3133
import java.util.concurrent.ThreadLocalRandom;
3234
import java.util.concurrent.TimeUnit;
3335
import java.util.function.Supplier;
36+
import java.util.logging.Level;
37+
import java.util.logging.Logger;
3438
import java.util.stream.Collectors;
3539
import javax.annotation.Nullable;
3640

3741
/** Class that manages the health checking in the BigtableChannelPool */
3842
class ChannelPoolHealthChecker {
3943

44+
private static final Logger logger = Logger.getLogger(ChannelPoolHealthChecker.class.getName());
45+
4046
// Configuration constants
4147
// Window_Duration is the duration over which we keep probe results
4248
private static final Duration WINDOW_DURATION = Duration.ofMinutes(5);
@@ -69,9 +75,12 @@ static ProbeResult create(Instant startTime, boolean success) {
6975

7076
private final Supplier<ImmutableList<Entry>> entrySupplier;
7177
private volatile Instant lastEviction;
72-
private ScheduledExecutorService executor;
78+
private final ScheduledExecutorService executor;
79+
80+
private final ChannelPrimer channelPrimer;
7381

74-
private ChannelPrimer channelPrimer;
82+
private ScheduledFuture<?> probeTaskScheduledFuture;
83+
private ScheduledFuture<?> detectAndRemoveTaskScheduledFuture;
7584

7685
private final Clock clock;
7786

@@ -89,54 +98,66 @@ public ChannelPoolHealthChecker(
8998
}
9099

91100
void start() {
92-
Duration initialDelayProbe =
93-
Duration.ofMillis(ThreadLocalRandom.current().nextLong(PROBE_INTERVAL.toMillis()));
94-
executor.scheduleAtFixedRate(
95-
this::runProbes,
96-
initialDelayProbe.toMillis(),
97-
PROBE_INTERVAL.toMillis(),
98-
TimeUnit.MILLISECONDS);
99-
Duration initialDelayDetect =
100-
Duration.ofMillis(ThreadLocalRandom.current().nextLong(PROBE_INTERVAL.toMillis()));
101-
executor.scheduleAtFixedRate(
102-
this::detectAndRemoveOutlierEntries,
103-
initialDelayDetect.toMillis(),
104-
PROBE_INTERVAL.toMillis(),
105-
TimeUnit.MILLISECONDS);
101+
if (channelPrimer instanceof BigtableChannelPrimer) {
102+
Duration initialDelayProbe =
103+
Duration.ofMillis(ThreadLocalRandom.current().nextLong(PROBE_INTERVAL.toMillis()));
104+
this.probeTaskScheduledFuture =
105+
executor.scheduleAtFixedRate(
106+
this::runProbes,
107+
initialDelayProbe.toMillis(),
108+
PROBE_INTERVAL.toMillis(),
109+
TimeUnit.MILLISECONDS);
110+
Duration initialDelayDetect =
111+
Duration.ofMillis(ThreadLocalRandom.current().nextLong(PROBE_INTERVAL.toMillis()));
112+
this.detectAndRemoveTaskScheduledFuture =
113+
executor.scheduleAtFixedRate(
114+
this::detectAndRemoveOutlierEntries,
115+
initialDelayDetect.toMillis(),
116+
PROBE_INTERVAL.toMillis(),
117+
TimeUnit.MILLISECONDS);
118+
} else {
119+
logger.log(Level.WARNING, "NoOpChannelPrimer was provided, not checking channel health.");
120+
}
106121
}
107122

108123
/** Stop running health checking */
109124
public void stop() {
110-
executor.shutdownNow();
125+
if (probeTaskScheduledFuture != null) {
126+
probeTaskScheduledFuture.cancel(true);
127+
}
128+
if (detectAndRemoveTaskScheduledFuture != null) {
129+
detectAndRemoveTaskScheduledFuture.cancel(true);
130+
}
111131
}
112132

113133
/** Runs probes on all the channels in the pool. */
114134
@VisibleForTesting
115135
void runProbes() {
116136
for (Entry entry : this.entrySupplier.get()) {
117137
final Instant startTime = clock.instant();
118-
final SettableApiFuture<PingAndWarmResponse> probeFuture;
138+
final ApiFuture<PingAndWarmResponse> probeFuture;
119139

120140
if (channelPrimer instanceof BigtableChannelPrimer) {
121141
BigtableChannelPrimer primer = (BigtableChannelPrimer) channelPrimer;
122142
probeFuture = primer.sendPrimeRequestsAsync(entry.getManagedChannel());
123143
} else {
124144
continue;
125145
}
126-
probeFuture.addListener(() -> onComplete(entry, startTime, probeFuture), executor);
146+
probeFuture.addListener(
147+
() -> onComplete(entry, startTime, probeFuture), MoreExecutors.directExecutor());
127148
}
128149
}
129150

130151
/** Callback that will update Entry data on probe complete. */
131152
@VisibleForTesting
132-
void onComplete(
133-
Entry entry, Instant startTime, SettableApiFuture<PingAndWarmResponse> probeFuture) {
153+
void onComplete(Entry entry, Instant startTime, ApiFuture<PingAndWarmResponse> probeFuture) {
134154
boolean success;
135155
try {
136156
probeFuture.get(PROBE_DEADLINE.toMillis(), TimeUnit.MILLISECONDS);
137157
success = true;
138158
} catch (Exception e) {
139159
success = false;
160+
logger.log(Level.WARNING, "Probe failed");
140161
}
141162
addProbeResult(entry, ProbeResult.create(startTime, success));
142163
}
@@ -219,6 +240,9 @@ void detectAndRemoveOutlierEntries() {
219240
Entry outlier = findOutlierEntry();
220241
if (outlier != null) {
221242
this.lastEviction = clock.instant();
243+
outlier.failedProbesInWindow.set(0);
244+
outlier.successfulProbesInWindow.set(0);
245+
outlier.probeHistory.clear();
222246
outlier.getManagedChannel().enterIdle();
223247
}
224248
}

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/grpc/ChannelPrimer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
*/
1616
package com.google.cloud.bigtable.gaxx.grpc;
1717

18+
import com.google.api.core.ApiFuture;
1819
import com.google.api.core.InternalApi;
19-
import com.google.api.core.SettableApiFuture;
2020
import com.google.bigtable.v2.PingAndWarmResponse;
2121
import io.grpc.ManagedChannel;
2222

2323
@InternalApi("For internal use by google-cloud-java clients only")
2424
public interface ChannelPrimer {
2525
void primeChannel(ManagedChannel var1);
2626

27-
SettableApiFuture<PingAndWarmResponse> sendPrimeRequestsAsync(ManagedChannel var1);
27+
ApiFuture<PingAndWarmResponse> sendPrimeRequestsAsync(ManagedChannel var1);
2828
}

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/BigtableChannelPrimerTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import static org.junit.Assert.assertThrows;
2020

2121
import com.google.api.core.ApiFunction;
22-
import com.google.api.core.SettableApiFuture;
22+
import com.google.api.core.ApiFuture;
2323
import com.google.auth.oauth2.AccessToken;
2424
import com.google.auth.oauth2.OAuth2Credentials;
2525
import com.google.bigtable.v2.BigtableGrpc.BigtableImplBase;
@@ -173,7 +173,7 @@ public void testHeadersAreSent() {
173173
// New test for the async success path
174174
@Test
175175
public void testAsyncSuccess() throws Exception {
176-
SettableApiFuture<PingAndWarmResponse> future = primer.sendPrimeRequestsAsync(channel);
176+
ApiFuture<PingAndWarmResponse> future = primer.sendPrimeRequestsAsync(channel);
177177

178178
PingAndWarmResponse response = future.get(1, TimeUnit.SECONDS);
179179
assertThat(response).isNotNull();
@@ -192,7 +192,7 @@ public PingAndWarmResponse apply(PingAndWarmRequest pingAndWarmRequest) {
192192
}
193193
};
194194

195-
SettableApiFuture<PingAndWarmResponse> future = primer.sendPrimeRequestsAsync(channel);
195+
ApiFuture<PingAndWarmResponse> future = primer.sendPrimeRequestsAsync(channel);
196196

197197
ExecutionException e =
198198
assertThrows(ExecutionException.class, () -> future.get(5, TimeUnit.SECONDS));

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/gaxx/grpc/HealthChecker.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package com.google.cloud.bigtable.gaxx.grpc;
1717

18+
import com.google.api.core.InternalApi;
19+
20+
@InternalApi
1821
public interface HealthChecker {
1922
void start();
2023

0 commit comments

Comments
 (0)