Skip to content

Commit b518d68

Browse files
authored
feat: add APIs to enable batch write flow control (#1730)
* feat: add APIs to enable batch write flow control * address comments
1 parent ee0da11 commit b518d68

File tree

5 files changed

+77
-3
lines changed

5 files changed

+77
-3
lines changed

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.google.cloud.bigtable.data.v2;
1717

1818
import com.google.api.core.BetaApi;
19+
import com.google.api.core.InternalApi;
1920
import com.google.api.gax.batching.Batcher;
2021
import com.google.api.gax.batching.FlowController;
2122
import com.google.api.gax.core.CredentialsProvider;
@@ -278,6 +279,15 @@ public Long getBatchMutationsTargetRpcLatencyMs() {
278279
return stubSettings.bulkMutateRowsSettings().getTargetRpcLatencyMs();
279280
}
280281

282+
/**
283+
* Gets if flow control is enabled for {@link BigtableDataClient#newBulkMutationBatcher(String)}
284+
* based on the load of the Bigtable server.
285+
*/
286+
@InternalApi("Intended for use by the Bigtable dataflow connectors only")
287+
public boolean isBulkMutationFlowControlEnabled() {
288+
return stubSettings.bulkMutateRowsSettings().isServerInitiatedFlowControlEnabled();
289+
}
290+
281291
/** Returns the underlying RPC settings. */
282292
public EnhancedBigtableStubSettings getStubSettings() {
283293
return stubSettings;
@@ -505,6 +515,28 @@ public Long getTargetRpcLatencyMsForBatchMutation() {
505515
return stubSettings.bulkMutateRowsSettings().getTargetRpcLatencyMs();
506516
}
507517

518+
/**
519+
* Configure flow control for {@link BigtableDataClient#newBulkMutationBatcher(String)} based on
520+
* the current load on the Bigtable cluster.
521+
*
522+
* <p>This is different from the {@link FlowController} that's always enabled on batch reads and
523+
* batch writes, which limits the number of outstanding requests to the Bigtable server.
524+
*/
525+
@InternalApi("Intended for use by the Bigtable dataflow connectors only")
526+
public Builder setBulkMutationFlowControl(boolean isEnableFlowControl) {
527+
stubSettings.bulkMutateRowsSettings().setServerInitiatedFlowControl(isEnableFlowControl);
528+
return this;
529+
}
530+
531+
/**
532+
* Gets if flow control is enabled for {@link BigtableDataClient#newBulkMutationBatcher(String)}
533+
* based on the load of the Bigtable server.
534+
*/
535+
@InternalApi("Intended for use by the Bigtable dataflow connectors only")
536+
public boolean isBulkMutationFlowControlEnabled() {
537+
return stubSettings.bulkMutateRowsSettings().isServerInitiatedFlowControlEnabled();
538+
}
539+
508540
/**
509541
* Returns the underlying settings for making RPC calls. The settings should be changed with
510542
* care.

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.google.cloud.bigtable.data.v2.stub;
1717

1818
import com.google.api.core.BetaApi;
19+
import com.google.api.core.InternalApi;
1920
import com.google.api.gax.batching.BatchingCallSettings;
2021
import com.google.api.gax.batching.BatchingDescriptor;
2122
import com.google.api.gax.batching.BatchingSettings;
@@ -66,6 +67,8 @@ public final class BigtableBatchingCallSettings extends UnaryCallSettings<BulkMu
6667
private final Long targetRpcLatencyMs;
6768
private final DynamicFlowControlSettings dynamicFlowControlSettings;
6869

70+
private final boolean isServerInitiatedFlowControlEnabled;
71+
6972
private BigtableBatchingCallSettings(Builder builder) {
7073
super(builder);
7174
batchingCallSettings =
@@ -77,6 +80,7 @@ private BigtableBatchingCallSettings(Builder builder) {
7780
this.isLatencyBasedThrottlingEnabled = builder.isLatencyBasedThrottlingEnabled;
7881
this.targetRpcLatencyMs = builder.targetRpcLatencyMs;
7982
this.dynamicFlowControlSettings = builder.dynamicFlowControlSettings;
83+
this.isServerInitiatedFlowControlEnabled = builder.isServerInitiatedFlowControlEnabled;
8084
}
8185

8286
/** Returns batching settings which contains multiple batch threshold levels. */
@@ -109,6 +113,12 @@ DynamicFlowControlSettings getDynamicFlowControlSettings() {
109113
return dynamicFlowControlSettings;
110114
}
111115

116+
/** Gets if flow control is enabled. */
117+
@InternalApi("Intended for use by the Bigtable dataflow connectors only")
118+
public boolean isServerInitiatedFlowControlEnabled() {
119+
return isServerInitiatedFlowControlEnabled;
120+
}
121+
112122
static Builder newBuilder(
113123
BatchingDescriptor<RowMutationEntry, Void, BulkMutation, Void> batchingDescriptor) {
114124
return new Builder(batchingDescriptor);
@@ -130,6 +140,7 @@ public String toString() {
130140
.add("isLatencyBasedThrottlingEnabled", isLatencyBasedThrottlingEnabled)
131141
.add("targetRpcLatency", targetRpcLatencyMs)
132142
.add("dynamicFlowControlSettings", dynamicFlowControlSettings)
143+
.add("isServerInitiatedFlowControlEnabled", isServerInitiatedFlowControlEnabled)
133144
.toString();
134145
}
135146

@@ -145,6 +156,8 @@ public static class Builder extends UnaryCallSettings.Builder<BulkMutation, Void
145156
private Long targetRpcLatencyMs;
146157
private DynamicFlowControlSettings dynamicFlowControlSettings;
147158

159+
private boolean isServerInitiatedFlowControlEnabled;
160+
148161
private Builder(
149162
@Nonnull
150163
BatchingDescriptor<RowMutationEntry, Void, BulkMutation, Void> batchingDescriptor) {
@@ -159,6 +172,7 @@ private Builder(@Nonnull BigtableBatchingCallSettings settings) {
159172
this.isLatencyBasedThrottlingEnabled = settings.isLatencyBasedThrottlingEnabled();
160173
this.targetRpcLatencyMs = settings.getTargetRpcLatencyMs();
161174
this.dynamicFlowControlSettings = settings.getDynamicFlowControlSettings();
175+
this.isServerInitiatedFlowControlEnabled = settings.isServerInitiatedFlowControlEnabled();
162176
}
163177

164178
/** Sets the batching settings with various thresholds. */
@@ -263,6 +277,19 @@ DynamicFlowControlSettings getDynamicFlowControlSettings() {
263277
return this.dynamicFlowControlSettings;
264278
}
265279

280+
/** Configure flow control based on the current load of the Bigtable server. */
281+
@InternalApi("Intended for use by the Bigtable dataflow connectors only")
282+
public Builder setServerInitiatedFlowControl(boolean isEnable) {
283+
this.isServerInitiatedFlowControlEnabled = isEnable;
284+
return this;
285+
}
286+
287+
/** Gets if flow control is enabled based on the load of the Bigtable server. */
288+
@InternalApi("Intended for use by the Bigtable dataflow connectors only")
289+
public boolean isServerInitiatedFlowControlEnabled() {
290+
return this.isServerInitiatedFlowControlEnabled;
291+
}
292+
266293
/** Builds the {@link BigtableBatchingCallSettings} object with provided configuration. */
267294
@Override
268295
public BigtableBatchingCallSettings build() {

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,15 +733,19 @@ public Map<String, String> extract(MutateRowsRequest mutateRowsRequest) {
733733
.build(),
734734
settings.bulkMutateRowsSettings().getRetryableCodes());
735735

736-
ServerStreamingCallable<MutateRowsRequest, MutateRowsResponse> withStatsHeaders =
736+
ServerStreamingCallable<MutateRowsRequest, MutateRowsResponse> callable =
737737
new StatsHeadersServerStreamingCallable<>(base);
738738

739+
if (settings.bulkMutateRowsSettings().isServerInitiatedFlowControlEnabled()) {
740+
callable = new RateLimitingServerStreamingCallable(callable);
741+
}
742+
739743
// Sometimes MutateRows connections are disconnected via an RST frame. This error is transient
740744
// and
741745
// should be treated similar to UNAVAILABLE. However, this exception has an INTERNAL error code
742746
// which by default is not retryable. Convert the exception so it can be retried in the client.
743747
ServerStreamingCallable<MutateRowsRequest, MutateRowsResponse> convertException =
744-
new ConvertExceptionCallable<>(withStatsHeaders);
748+
new ConvertExceptionCallable<>(callable);
745749

746750
RetryAlgorithm<Void> retryAlgorithm =
747751
new RetryAlgorithm<>(

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public void testToString() {
3636
// disable channel priming so we won't need authentication
3737
// for sending the prime request since we're only testing the settings.
3838
.setRefreshingChannel(false)
39+
.setBulkMutationFlowControl(true)
3940
.build();
4041
EnhancedBigtableStubSettings stubSettings = settings.getStubSettings();
4142
assertThat(settings.toString())

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ public void testBuilder() {
9696
assertThat(settings.getDynamicFlowControlSettings()).isNotNull();
9797
verifyFlowControlSettingWhenLatencyBasedThrottlingDisabled(
9898
settings.getDynamicFlowControlSettings());
99+
100+
builder.setServerInitiatedFlowControl(true);
101+
settings = builder.build();
102+
assertThat(settings.isServerInitiatedFlowControlEnabled()).isTrue();
103+
104+
builder.setServerInitiatedFlowControl(false);
105+
settings = builder.build();
106+
assertThat(settings.isServerInitiatedFlowControlEnabled()).isFalse();
99107
}
100108

101109
@Test
@@ -108,7 +116,8 @@ public void testBuilderFromSettings() {
108116
.setBatchingSettings(BATCHING_SETTINGS)
109117
.setRetryableCodes(StatusCode.Code.UNAVAILABLE, StatusCode.Code.UNAUTHENTICATED)
110118
.setRetrySettings(retrySettings)
111-
.enableLatencyBasedThrottling(10L);
119+
.enableLatencyBasedThrottling(10L)
120+
.setServerInitiatedFlowControl(true);
112121

113122
BigtableBatchingCallSettings settings = builder.build();
114123
BigtableBatchingCallSettings.Builder newBuilder = settings.toBuilder();
@@ -122,6 +131,7 @@ public void testBuilderFromSettings() {
122131
assertThat(newBuilder.getDynamicFlowControlSettings()).isNotNull();
123132
verifyFlowControlSettingWhenLatencyBasedThrottlingEnabled(
124133
newBuilder.getDynamicFlowControlSettings());
134+
assertThat(newBuilder.isServerInitiatedFlowControlEnabled()).isTrue();
125135
}
126136

127137
@Test

0 commit comments

Comments
 (0)