Skip to content

Commit eabb07a

Browse files
committed
feat: introduce Bigtable Admin V2 clients for Selective GAPIC
This commit adds `BigtableTableAdminClientV2` and `BigtableInstanceAdminClientV2`, which extend the autogenerated base clients. These classes serve as the new, independent entry points for the Selective GAPIC hierarchy. For `BigtableTableAdminClientV2`, the manual wrappers for Critical User Journeys (CUJs) like `awaitOptimizeRestoredTable` and `waitForConsistency` have been relocated from the legacy client. It utilizes the new context-free ConsistencyRequest factories introduced in the previous refactoring step. For `BigtableInstanceAdminClientV2`, the class acts as a standardized entry point, as no manual overrides were required from the legacy client. b/502616786
1 parent b68d628 commit eabb07a

File tree

4 files changed

+427
-0
lines changed

4 files changed

+427
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2026 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.admin.v2;
17+
18+
import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub;
19+
import java.io.IOException;
20+
21+
/**
22+
* Modern Cloud Bigtable Instance Admin Client.
23+
*
24+
* <p>This client extends the auto-generated {@link BaseBigtableInstanceAdminClient} to provide
25+
* manual overrides and additional convenience methods for Critical User Journeys (CUJs) that the
26+
* GAPIC generator cannot handle natively.
27+
*/
28+
public class BigtableInstanceAdminClientV2 extends BaseBigtableInstanceAdminClient {
29+
30+
protected BigtableInstanceAdminClientV2(BaseBigtableInstanceAdminSettings settings)
31+
throws IOException {
32+
super(settings);
33+
}
34+
35+
protected BigtableInstanceAdminClientV2(BigtableInstanceAdminStub stub) {
36+
super(stub);
37+
}
38+
39+
/** Constructs an instance of BigtableInstanceAdminClientV2 with the given settings. */
40+
public static final BigtableInstanceAdminClientV2 createClient(
41+
BaseBigtableInstanceAdminSettings settings) throws IOException {
42+
return new BigtableInstanceAdminClientV2(settings);
43+
}
44+
45+
/** Constructs an instance of BigtableInstanceAdminClientV2 with the given stub. */
46+
public static final BigtableInstanceAdminClientV2 createClient(BigtableInstanceAdminStub stub) {
47+
return new BigtableInstanceAdminClientV2(stub);
48+
}
49+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Copyright 2026 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.admin.v2;
17+
18+
import com.google.api.core.ApiFuture;
19+
import com.google.api.core.ApiFutures;
20+
import com.google.api.gax.rpc.ApiExceptions;
21+
import com.google.cloud.bigtable.admin.v2.models.ConsistencyRequest;
22+
import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken;
23+
import com.google.cloud.bigtable.admin.v2.models.RestoredTableResult;
24+
import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStub;
25+
import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub;
26+
import com.google.common.base.Strings;
27+
import com.google.protobuf.Empty;
28+
import java.io.IOException;
29+
import java.util.concurrent.ExecutionException;
30+
31+
/**
32+
* Modern Cloud Bigtable Table Admin Client.
33+
*
34+
* <p>This client extends the auto-generated {@link BaseBigtableTableAdminClient} to provide manual
35+
* overrides and additional convenience methods for Critical User Journeys (CUJs) that the GAPIC
36+
* generator cannot handle natively (e.g., chained Long Running Operations, Consistency Polling).
37+
*/
38+
public class BigtableTableAdminClientV2 extends BaseBigtableTableAdminClient {
39+
40+
protected BigtableTableAdminClientV2(BaseBigtableTableAdminSettings settings) throws IOException {
41+
super(settings);
42+
}
43+
44+
protected BigtableTableAdminClientV2(BigtableTableAdminStub stub) {
45+
super(stub);
46+
}
47+
48+
/** Constructs an instance of BigtableTableAdminClientV2 with the given settings. */
49+
public static final BigtableTableAdminClientV2 createClient(BaseBigtableTableAdminSettings settings)
50+
throws IOException {
51+
// Explicitly create the enhanced stub
52+
EnhancedBigtableTableAdminStub stub =
53+
EnhancedBigtableTableAdminStub.createEnhanced(
54+
(com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings) settings.getStubSettings());
55+
// Pass the enhanced stub to the existing stub-based constructor
56+
return new BigtableTableAdminClientV2(stub);
57+
}
58+
59+
/** Constructs an instance of BigtableTableAdminClientV2 with the given stub. */
60+
public static final BigtableTableAdminClientV2 createClient(BigtableTableAdminStub stub) {
61+
return new BigtableTableAdminClientV2(stub);
62+
}
63+
64+
/**
65+
* Awaits the completion of the "Optimize Restored Table" operation.
66+
*
67+
* <p>This method blocks until the restore operation is complete, extracts the optimization token,
68+
* and returns an ApiFuture for the optimization phase.
69+
*
70+
* @param restoreFuture The future returned by restoreTableAsync().
71+
* @return An ApiFuture that tracks the optimization progress.
72+
*/
73+
public ApiFuture<Empty> awaitOptimizeRestoredTable(ApiFuture<RestoredTableResult> restoreFuture) {
74+
// 1. Block and wait for the restore operation to complete
75+
RestoredTableResult result;
76+
try {
77+
result = restoreFuture.get();
78+
} catch (Exception e) {
79+
throw new RuntimeException("Restore operation failed", e);
80+
}
81+
82+
// 2. Extract the operation token from the result
83+
// (RestoredTableResult already wraps the OptimizeRestoredTableOperationToken)
84+
OptimizeRestoredTableOperationToken token = result.getOptimizeRestoredTableOperationToken();
85+
86+
if (token == null || Strings.isNullOrEmpty(token.getOperationName())) {
87+
// If there is no optimization operation, return immediate success.
88+
return ApiFutures.immediateFuture(Empty.getDefaultInstance());
89+
}
90+
91+
// 3. Return the future for the optimization operation
92+
return ((EnhancedBigtableTableAdminStub) getStub()).awaitOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName());
93+
}
94+
95+
/**
96+
* Awaits a restored table is fully optimized.
97+
*
98+
* <p>Sample code
99+
*
100+
* <pre>{@code
101+
* RestoredTableResult result =
102+
* client.restoreTable(RestoreTableRequest.of(clusterId, backupId).setTableId(tableId));
103+
* client.awaitOptimizeRestoredTable(result.getOptimizeRestoredTableOperationToken());
104+
* }</pre>
105+
*/
106+
public void awaitOptimizeRestoredTable(OptimizeRestoredTableOperationToken token)
107+
throws ExecutionException, InterruptedException {
108+
awaitOptimizeRestoredTableAsync(token).get();
109+
}
110+
111+
/**
112+
* Awaits a restored table is fully optimized asynchronously.
113+
*
114+
* <p>Sample code
115+
*
116+
* <pre>{@code
117+
* RestoredTableResult result =
118+
* client.restoreTable(RestoreTableRequest.of(clusterId, backupId).setTableId(tableId));
119+
* ApiFuture<Void> future = client.awaitOptimizeRestoredTableAsync(
120+
* result.getOptimizeRestoredTableOperationToken());
121+
*
122+
* ApiFutures.addCallback(
123+
* future,
124+
* new ApiFutureCallback<Void>() {
125+
* public void onSuccess(Void unused) {
126+
* System.out.println("The optimization of the restored table is done.");
127+
* }
128+
*
129+
* public void onFailure(Throwable t) {
130+
* t.printStackTrace();
131+
* }
132+
* },
133+
* MoreExecutors.directExecutor()
134+
* );
135+
* }</pre>
136+
*/
137+
public ApiFuture<Void> awaitOptimizeRestoredTableAsync(
138+
OptimizeRestoredTableOperationToken token) {
139+
ApiFuture<Empty> emptyFuture =
140+
((EnhancedBigtableTableAdminStub) getStub()).awaitOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName());
141+
return ApiFutures.transform(
142+
emptyFuture,
143+
new com.google.api.core.ApiFunction<Empty, Void>() {
144+
@Override
145+
public Void apply(Empty input) {
146+
return null;
147+
}
148+
},
149+
com.google.common.util.concurrent.MoreExecutors.directExecutor());
150+
}
151+
152+
/**
153+
* Polls an existing consistency token until table replication is consistent across all clusters.
154+
* Useful for checking consistency of a token generated in a separate process. Blocks until
155+
* completion.
156+
*
157+
* @param tableName The fully qualified table name to check.
158+
* @param consistencyToken The token to poll.
159+
*/
160+
public void waitForConsistency(String tableName, String consistencyToken) {
161+
ApiExceptions.callAndTranslateApiException(waitForConsistencyAsync(tableName, consistencyToken));
162+
}
163+
164+
/**
165+
* Asynchronously polls the consistency token. Returns a future that completes when table
166+
* replication is consistent across all clusters.
167+
*
168+
* @param tableName The fully qualified table name to check.
169+
* @param consistencyToken The token to poll.
170+
*/
171+
public ApiFuture<Void> waitForConsistencyAsync(String tableName, String consistencyToken) {
172+
return ((EnhancedBigtableTableAdminStub) getStub()).awaitConsistencyCallable()
173+
.futureCall(ConsistencyRequest.forReplicationFromTableName(tableName, consistencyToken));
174+
}
175+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2026 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.admin.v2;
17+
18+
import static com.google.common.truth.Truth.assertThat;
19+
20+
import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub;
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.junit.runners.JUnit4;
24+
import org.mockito.Mockito;
25+
26+
@RunWith(JUnit4.class)
27+
public class BigtableInstanceAdminClientV2Test {
28+
29+
@Test
30+
public void testCreateWithStub() {
31+
BigtableInstanceAdminStub mockStub = Mockito.mock(BigtableInstanceAdminStub.class);
32+
BigtableInstanceAdminClientV2 client = BigtableInstanceAdminClientV2.createClient(mockStub);
33+
34+
assertThat(client).isNotNull();
35+
}
36+
37+
@Test
38+
public void testCreateClientWithSettings() throws Exception {
39+
BaseBigtableInstanceAdminSettings settings =
40+
BaseBigtableInstanceAdminSettings.newBuilder()
41+
.setCredentialsProvider(com.google.api.gax.core.NoCredentialsProvider.create())
42+
.build();
43+
try (BigtableInstanceAdminClientV2 settingsClient =
44+
BigtableInstanceAdminClientV2.createClient(settings)) {
45+
assertThat(settingsClient).isNotNull();
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)