32
32
import com .google .api .gax .rpc .TransportChannelProvider ;
33
33
import com .google .api .gax .rpc .UnaryCallSettings ;
34
34
import com .google .auth .Credentials ;
35
+ import com .google .bigtable .v2 .FeatureFlags ;
35
36
import com .google .bigtable .v2 .PingAndWarmRequest ;
36
37
import com .google .cloud .bigtable .Version ;
37
38
import com .google .cloud .bigtable .data .v2 .models .ChangeStreamRecord ;
50
51
import com .google .common .collect .ImmutableList ;
51
52
import com .google .common .collect .ImmutableMap ;
52
53
import com .google .common .collect .ImmutableSet ;
54
+ import java .io .ByteArrayOutputStream ;
53
55
import java .io .IOException ;
56
+ import java .nio .charset .StandardCharsets ;
57
+ import java .util .Base64 ;
54
58
import java .util .List ;
55
59
import java .util .Map ;
56
60
import java .util .Set ;
@@ -221,6 +225,8 @@ public class EnhancedBigtableStubSettings extends StubSettings<EnhancedBigtableS
221
225
readChangeStreamSettings ;
222
226
private final UnaryCallSettings <PingAndWarmRequest , Void > pingAndWarmSettings ;
223
227
228
+ private final FeatureFlags featureFlags ;
229
+
224
230
private EnhancedBigtableStubSettings (Builder builder ) {
225
231
super (builder );
226
232
@@ -259,6 +265,7 @@ private EnhancedBigtableStubSettings(Builder builder) {
259
265
builder .generateInitialChangeStreamPartitionsSettings .build ();
260
266
readChangeStreamSettings = builder .readChangeStreamSettings .build ();
261
267
pingAndWarmSettings = builder .pingAndWarmSettings .build ();
268
+ featureFlags = builder .featureFlags .build ();
262
269
}
263
270
264
271
/** Create a new builder. */
@@ -598,6 +605,8 @@ public static class Builder extends StubSettings.Builder<EnhancedBigtableStubSet
598
605
readChangeStreamSettings ;
599
606
private final UnaryCallSettings .Builder <PingAndWarmRequest , Void > pingAndWarmSettings ;
600
607
608
+ private FeatureFlags .Builder featureFlags ;
609
+
601
610
/**
602
611
* Initializes a new Builder with sane defaults for all settings.
603
612
*
@@ -621,16 +630,6 @@ private Builder() {
621
630
setStreamWatchdogCheckInterval (baseDefaults .getStreamWatchdogCheckInterval ());
622
631
setStreamWatchdogProvider (baseDefaults .getStreamWatchdogProvider ());
623
632
624
- // Inject the UserAgent in addition to api-client header
625
- Map <String , String > headers =
626
- ImmutableMap .<String , String >builder ()
627
- .putAll (
628
- BigtableStubSettings .defaultApiClientHeaderProviderBuilder ().build ().getHeaders ())
629
- // GrpcHeaderInterceptor treats the `user-agent` as a magic string
630
- .put ("user-agent" , "bigtable-java/" + Version .VERSION )
631
- .build ();
632
- setInternalHeaderProvider (FixedHeaderProvider .create (headers ));
633
-
634
633
// Per-method settings using baseSettings for defaults.
635
634
readRowsSettings = ServerStreamingCallSettings .newBuilder ();
636
635
@@ -729,6 +728,8 @@ private Builder() {
729
728
.setMaxRpcTimeout (PRIME_REQUEST_TIMEOUT )
730
729
.setTotalTimeout (PRIME_REQUEST_TIMEOUT )
731
730
.build ());
731
+
732
+ featureFlags = FeatureFlags .newBuilder ();
732
733
}
733
734
734
735
private Builder (EnhancedBigtableStubSettings settings ) {
@@ -753,6 +754,7 @@ private Builder(EnhancedBigtableStubSettings settings) {
753
754
settings .generateInitialChangeStreamPartitionsSettings .toBuilder ();
754
755
readChangeStreamSettings = settings .readChangeStreamSettings .toBuilder ();
755
756
pingAndWarmSettings = settings .pingAndWarmSettings .toBuilder ();
757
+ featureFlags = settings .featureFlags .toBuilder ();
756
758
}
757
759
// <editor-fold desc="Private Helpers">
758
760
@@ -970,6 +972,34 @@ public EnhancedBigtableStubSettings build() {
970
972
BigtableChannelPrimer .create (credentials , projectId , instanceId , appProfileId ));
971
973
this .setTransportChannelProvider (channelProviderBuilder .build ());
972
974
}
975
+
976
+ if (this .bulkMutateRowsSettings ().isServerInitiatedFlowControlEnabled ()) {
977
+ // only set mutate rows feature flag when this feature is enabled
978
+ featureFlags .setMutateRowsRateLimit (true );
979
+ }
980
+
981
+ // Serialize the web64 encode the bigtable feature flags
982
+ ByteArrayOutputStream boas = new ByteArrayOutputStream ();
983
+ try {
984
+ featureFlags .build ().writeTo (boas );
985
+ } catch (IOException e ) {
986
+ throw new IllegalStateException (
987
+ "Unexpected IOException while serializing feature flags" , e );
988
+ }
989
+ byte [] serializedFlags = boas .toByteArray ();
990
+ byte [] encodedFlags = Base64 .getUrlEncoder ().encode (serializedFlags );
991
+
992
+ // Inject the UserAgent in addition to api-client header
993
+ Map <String , String > headers =
994
+ ImmutableMap .<String , String >builder ()
995
+ .putAll (
996
+ BigtableStubSettings .defaultApiClientHeaderProviderBuilder ().build ().getHeaders ())
997
+ // GrpcHeaderInterceptor treats the `user-agent` as a magic string
998
+ .put ("user-agent" , "bigtable-java/" + Version .VERSION )
999
+ .put ("bigtable-features" , new String (encodedFlags , StandardCharsets .UTF_8 ))
1000
+ .build ();
1001
+ setInternalHeaderProvider (FixedHeaderProvider .create (headers ));
1002
+
973
1003
return new EnhancedBigtableStubSettings (this );
974
1004
}
975
1005
// </editor-fold>
0 commit comments