Skip to content

Commit 656684b

Browse files
fix: add missing api-client header (#290)
* fix: add missing api-client header When migrating to custom callable chains, wI accidentally forgot to pull the api client header provider to the enhanced settings. * codestyle * codestyle
1 parent 592ff87 commit 656684b

File tree

3 files changed

+238
-161
lines changed

3 files changed

+238
-161
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ private Builder() {
519519
setTransportChannelProvider(defaultTransportChannelProvider());
520520
setStreamWatchdogCheckInterval(baseDefaults.getStreamWatchdogCheckInterval());
521521
setStreamWatchdogProvider(baseDefaults.getStreamWatchdogProvider());
522+
setHeaderProvider(BigtableStubSettings.defaultApiClientHeaderProviderBuilder().build());
522523

523524
setTracerFactory(
524525
new OpencensusTracerFactory(
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigtable.data.v2.stub;
17+
18+
import static com.google.common.truth.Truth.assertThat;
19+
20+
import com.google.api.gax.batching.Batcher;
21+
import com.google.bigtable.v2.BigtableGrpc;
22+
import com.google.bigtable.v2.CheckAndMutateRowRequest;
23+
import com.google.bigtable.v2.CheckAndMutateRowResponse;
24+
import com.google.bigtable.v2.MutateRowRequest;
25+
import com.google.bigtable.v2.MutateRowResponse;
26+
import com.google.bigtable.v2.MutateRowsRequest;
27+
import com.google.bigtable.v2.MutateRowsResponse;
28+
import com.google.bigtable.v2.ReadModifyWriteRowRequest;
29+
import com.google.bigtable.v2.ReadModifyWriteRowResponse;
30+
import com.google.bigtable.v2.ReadRowsRequest;
31+
import com.google.bigtable.v2.ReadRowsResponse;
32+
import com.google.bigtable.v2.SampleRowKeysRequest;
33+
import com.google.bigtable.v2.SampleRowKeysResponse;
34+
import com.google.cloud.bigtable.data.v2.BigtableDataClient;
35+
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
36+
import com.google.cloud.bigtable.data.v2.internal.NameUtil;
37+
import com.google.cloud.bigtable.data.v2.models.*;
38+
import com.google.cloud.bigtable.data.v2.models.Mutation;
39+
import com.google.rpc.Status;
40+
import io.grpc.Metadata;
41+
import io.grpc.Server;
42+
import io.grpc.ServerBuilder;
43+
import io.grpc.ServerCall;
44+
import io.grpc.ServerCallHandler;
45+
import io.grpc.ServerInterceptor;
46+
import io.grpc.stub.StreamObserver;
47+
import java.net.ServerSocket;
48+
import java.util.concurrent.ArrayBlockingQueue;
49+
import java.util.concurrent.BlockingQueue;
50+
import org.junit.After;
51+
import org.junit.Before;
52+
import org.junit.Test;
53+
import org.junit.runner.RunWith;
54+
import org.junit.runners.JUnit4;
55+
56+
@RunWith(JUnit4.class)
57+
public class HeadersTest {
58+
private static final String PROJECT_ID = "fake-project";
59+
private static final String INSTANCE_ID = "fake-instance";
60+
private static final String TABLE_ID = "fake-table";
61+
private static final String TABLE_NAME =
62+
NameUtil.formatTableName(PROJECT_ID, INSTANCE_ID, TABLE_ID);
63+
private static final String APP_PROFILE_ID = "fake-profile";
64+
65+
private static final Metadata.Key<String> X_GOOG_REQUEST_PARAMS_KEY =
66+
Metadata.Key.of("x-goog-request-params", Metadata.ASCII_STRING_MARSHALLER);
67+
private static final Metadata.Key<String> API_CLIENT_HEADER_KEY =
68+
Metadata.Key.of("x-goog-api-client", Metadata.ASCII_STRING_MARSHALLER);
69+
70+
private Server server;
71+
private BlockingQueue<Metadata> sentMetadata = new ArrayBlockingQueue<>(10);
72+
73+
private BigtableDataClient client;
74+
75+
@Before
76+
public void setUp() throws Exception {
77+
int port;
78+
try (ServerSocket ss = new ServerSocket(0)) {
79+
port = ss.getLocalPort();
80+
}
81+
server =
82+
ServerBuilder.forPort(port)
83+
.addService(new FakeBigtableService())
84+
.intercept(new MetadataInterceptor())
85+
.build();
86+
server.start();
87+
88+
BigtableDataSettings.Builder settings =
89+
BigtableDataSettings.newBuilderForEmulator(port)
90+
.setProjectId(PROJECT_ID)
91+
.setInstanceId(INSTANCE_ID)
92+
.setAppProfileId(APP_PROFILE_ID);
93+
94+
// Force immediate flush
95+
settings
96+
.stubSettings()
97+
.bulkMutateRowsSettings()
98+
.setBatchingSettings(
99+
settings
100+
.stubSettings()
101+
.bulkMutateRowsSettings()
102+
.getBatchingSettings()
103+
.toBuilder()
104+
.setElementCountThreshold(1L)
105+
.build());
106+
107+
client = BigtableDataClient.create(settings.build());
108+
}
109+
110+
@After
111+
public void tearDown() throws Exception {
112+
client.close();
113+
server.shutdown();
114+
}
115+
116+
@Test
117+
public void readRowsTest() {
118+
client.readRows(Query.create(TABLE_ID));
119+
verifyHeaderSent();
120+
}
121+
122+
@Test
123+
public void sampleRowKeysTest() {
124+
client.sampleRowKeysAsync(TABLE_ID);
125+
verifyHeaderSent();
126+
}
127+
128+
@Test
129+
public void mutateRowTest() {
130+
client.mutateRowAsync(RowMutation.create(TABLE_ID, "fake-key").deleteRow());
131+
verifyHeaderSent();
132+
}
133+
134+
@Test
135+
public void mutateRowsTest() throws InterruptedException {
136+
try (Batcher<RowMutationEntry, Void> batcher = client.newBulkMutationBatcher(TABLE_ID)) {
137+
batcher.add(RowMutationEntry.create("fake-key").deleteRow());
138+
} catch (RuntimeException e) {
139+
// Ignore the errors: none of the methods are actually implemented
140+
}
141+
verifyHeaderSent();
142+
}
143+
144+
@Test
145+
public void checkAndMutateRowTest() {
146+
client.checkAndMutateRowAsync(
147+
ConditionalRowMutation.create(TABLE_ID, "fake-key").then(Mutation.create().deleteRow()));
148+
verifyHeaderSent();
149+
}
150+
151+
@Test
152+
public void readModifyWriteTest() {
153+
client.readModifyWriteRowAsync(
154+
ReadModifyWriteRow.create(TABLE_ID, "fake-key").increment("cf", "q", 1));
155+
verifyHeaderSent();
156+
}
157+
158+
private void verifyHeaderSent() {
159+
Metadata metadata;
160+
try {
161+
metadata = sentMetadata.take();
162+
} catch (InterruptedException e) {
163+
throw new RuntimeException(e);
164+
}
165+
166+
String requestParamsvalue = metadata.get(X_GOOG_REQUEST_PARAMS_KEY);
167+
assertThat(requestParamsvalue).containsMatch("(^|.*&)table_name=" + TABLE_NAME + "($|&.*)");
168+
assertThat(requestParamsvalue)
169+
.containsMatch("(^|.*&)app_profile_id=" + APP_PROFILE_ID + "($|&.*)");
170+
171+
String apiClientValue = metadata.get(API_CLIENT_HEADER_KEY);
172+
assertThat(apiClientValue).containsMatch("gl-java/[.\\d_]+");
173+
assertThat(apiClientValue).containsMatch("gax/[.\\d_]+");
174+
assertThat(apiClientValue).containsMatch("grpc/[.\\d_]+");
175+
}
176+
177+
private class MetadataInterceptor implements ServerInterceptor {
178+
@Override
179+
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
180+
ServerCall<ReqT, RespT> serverCall,
181+
Metadata metadata,
182+
ServerCallHandler<ReqT, RespT> serverCallHandler) {
183+
sentMetadata.add(metadata);
184+
185+
return serverCallHandler.startCall(serverCall, metadata);
186+
}
187+
}
188+
189+
private static class FakeBigtableService extends BigtableGrpc.BigtableImplBase {
190+
@Override
191+
public void readRows(
192+
ReadRowsRequest request, StreamObserver<ReadRowsResponse> responseObserver) {
193+
responseObserver.onCompleted();
194+
}
195+
196+
@Override
197+
public void sampleRowKeys(
198+
SampleRowKeysRequest request, StreamObserver<SampleRowKeysResponse> responseObserver) {
199+
responseObserver.onCompleted();
200+
}
201+
202+
@Override
203+
public void mutateRow(
204+
MutateRowRequest request, StreamObserver<MutateRowResponse> responseObserver) {
205+
responseObserver.onNext(MutateRowResponse.getDefaultInstance());
206+
responseObserver.onCompleted();
207+
}
208+
209+
@Override
210+
public void mutateRows(
211+
MutateRowsRequest request, StreamObserver<MutateRowsResponse> responseObserver) {
212+
responseObserver.onNext(
213+
MutateRowsResponse.newBuilder()
214+
.addEntries(
215+
MutateRowsResponse.Entry.newBuilder()
216+
.setIndex(0)
217+
.setStatus(Status.getDefaultInstance()))
218+
.build());
219+
responseObserver.onCompleted();
220+
}
221+
222+
@Override
223+
public void checkAndMutateRow(
224+
CheckAndMutateRowRequest request,
225+
StreamObserver<CheckAndMutateRowResponse> responseObserver) {
226+
responseObserver.onNext(CheckAndMutateRowResponse.getDefaultInstance());
227+
}
228+
229+
@Override
230+
public void readModifyWriteRow(
231+
ReadModifyWriteRowRequest request,
232+
StreamObserver<ReadModifyWriteRowResponse> responseObserver) {
233+
responseObserver.onNext(ReadModifyWriteRowResponse.getDefaultInstance());
234+
responseObserver.onCompleted();
235+
}
236+
}
237+
}

0 commit comments

Comments
 (0)