From b68d628de86acdc7aea3bdc7c15a7bb8f399fc24 Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Wed, 15 Apr 2026 14:35:08 -0400 Subject: [PATCH 01/14] refactor: decouple ConsistencyRequest from TableAdminRequestContext This commit updates the internal plumbing for `ConsistencyRequest` and `AwaitConsistencyCallable` to support fully qualified table names without breaking the existing public API for the legacy `BigtableTableAdminClient`. b/502616786 --- .../admin/v2/models/ConsistencyRequest.java | 45 +++++++++++++++++-- .../v2/stub/AwaitConsistencyCallable.java | 34 ++++++++++---- .../stub/EnhancedBigtableTableAdminStub.java | 10 ++++- 3 files changed, 77 insertions(+), 12 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java index f338776503..b463669603 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java @@ -43,9 +43,11 @@ public abstract class ConsistencyRequest { @Nullable public abstract String getConsistencyToken(); + protected abstract boolean isFullyQualified(); + public static ConsistencyRequest forReplication(String tableId) { return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null); + tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null, false); } /** @@ -59,17 +61,32 @@ public static ConsistencyRequest forReplication(String tableId, String consisten Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken); + tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken, false); } public static ConsistencyRequest forDataBoost(String tableId) { return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.DATA_BOOST_READ_LOCAL_WRITES, null); + tableId, CheckConsistencyRequest.ModeCase.DATA_BOOST_READ_LOCAL_WRITES, null, false); + } + + @InternalApi + public static ConsistencyRequest forReplicationFromTableName(String tableName) { + return new AutoValue_ConsistencyRequest( + tableName, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null, true); + } + + @InternalApi + public static ConsistencyRequest forReplicationFromTableName(String tableName, String consistencyToken) { + Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); + + return new AutoValue_ConsistencyRequest( + tableName, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken, true); } @InternalApi public CheckConsistencyRequest toCheckConsistencyProto( TableAdminRequestContext requestContext, String token) { + Preconditions.checkState(!isFullyQualified(), "Use toCheckConsistencyProto(String token) for fully qualified table names."); CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); @@ -83,13 +100,35 @@ public CheckConsistencyRequest toCheckConsistencyProto( return builder.setName(tableName.toString()).setConsistencyToken(token).build(); } + @InternalApi + public CheckConsistencyRequest toCheckConsistencyProto(String token) { + Preconditions.checkState(isFullyQualified(), "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table names."); + CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); + + if (getMode().equals(CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES)) { + builder.setStandardReadRemoteWrites(StandardReadRemoteWrites.newBuilder().build()); + } else { + builder.setDataBoostReadLocalWrites(DataBoostReadLocalWrites.newBuilder().build()); + } + + return builder.setName(getTableId()).setConsistencyToken(token).build(); + } + @InternalApi public GenerateConsistencyTokenRequest toGenerateTokenProto( TableAdminRequestContext requestContext) { + Preconditions.checkState(!isFullyQualified(), "Use toGenerateTokenProto() for fully qualified table names."); GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); return builder.setName(tableName.toString()).build(); } + + @InternalApi + public GenerateConsistencyTokenRequest toGenerateTokenProto() { + Preconditions.checkState(isFullyQualified(), "Use toGenerateTokenProto(TableAdminRequestContext) for non-qualified table names."); + GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); + return builder.setName(getTableId()).build(); + } } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java index b4e42e2354..a8ccdd9704 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java @@ -42,6 +42,7 @@ import com.google.common.util.concurrent.MoreExecutors; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; +import javax.annotation.Nullable; /** * Callable that waits until either replication or Data Boost has caught up to the point it was @@ -56,7 +57,7 @@ class AwaitConsistencyCallable extends UnaryCallable { private final UnaryCallable checkCallable; private final RetryingExecutor executor; - private final TableAdminRequestContext requestContext; + @Nullable private final TableAdminRequestContext requestContext; static AwaitConsistencyCallable create( UnaryCallable @@ -64,7 +65,7 @@ static AwaitConsistencyCallable create( UnaryCallable checkCallable, ClientContext clientContext, RetrySettings pollingSettings, - TableAdminRequestContext requestContext) { + @Nullable TableAdminRequestContext requestContext) { RetryAlgorithm retryAlgorithm = new RetryAlgorithm<>( @@ -78,13 +79,22 @@ static AwaitConsistencyCallable create( generateCallable, checkCallable, retryingExecutor, requestContext); } + static AwaitConsistencyCallable create( + UnaryCallable + generateCallable, + UnaryCallable checkCallable, + ClientContext clientContext, + RetrySettings pollingSettings) { + return create(generateCallable, checkCallable, clientContext, pollingSettings, null); + } + @VisibleForTesting AwaitConsistencyCallable( UnaryCallable generateCallable, UnaryCallable checkCallable, RetryingExecutor executor, - TableAdminRequestContext requestContext) { + @Nullable TableAdminRequestContext requestContext) { this.generateCallable = generateCallable; this.checkCallable = checkCallable; this.executor = executor; @@ -98,13 +108,19 @@ public ApiFuture futureCall( // If the token is already provided, skip generation and poll directly. if (consistencyRequest.getConsistencyToken() != null) { CheckConsistencyRequest request = - consistencyRequest.toCheckConsistencyProto( - requestContext, consistencyRequest.getConsistencyToken()); + requestContext == null + ? consistencyRequest.toCheckConsistencyProto(consistencyRequest.getConsistencyToken()) + : consistencyRequest.toCheckConsistencyProto( + requestContext, consistencyRequest.getConsistencyToken()); return pollToken(request, apiCallContext); } ApiFuture tokenFuture = - generateToken(consistencyRequest.toGenerateTokenProto(requestContext), apiCallContext); + generateToken( + requestContext == null + ? consistencyRequest.toGenerateTokenProto() + : consistencyRequest.toGenerateTokenProto(requestContext), + apiCallContext); return ApiFutures.transformAsync( tokenFuture, @@ -112,8 +128,10 @@ public ApiFuture futureCall( @Override public ApiFuture apply(GenerateConsistencyTokenResponse input) { CheckConsistencyRequest request = - consistencyRequest.toCheckConsistencyProto( - requestContext, input.getConsistencyToken()); + requestContext == null + ? consistencyRequest.toCheckConsistencyProto(input.getConsistencyToken()) + : consistencyRequest.toCheckConsistencyProto( + requestContext, input.getConsistencyToken()); return pollToken(request, apiCallContext); } }, diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java index e68cafca54..79da312d37 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java @@ -54,6 +54,7 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final BigtableTableAdminStubSettings settings; private final ClientContext clientContext; + @javax.annotation.Nullable private final TableAdminRequestContext requestContext; @Deprecated private final AwaitReplicationCallable awaitReplicationCallable; @@ -62,6 +63,13 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final OperationCallable optimizeRestoredTableOperationBaseCallable; + public static EnhancedBigtableTableAdminStub createEnhanced( + BigtableTableAdminStubSettings settings) + throws IOException { + return new EnhancedBigtableTableAdminStub( + settings, ClientContext.create(settings), null); + } + public static EnhancedBigtableTableAdminStub createEnhanced( BigtableTableAdminStubSettings settings, TableAdminRequestContext requestContext) throws IOException { @@ -72,7 +80,7 @@ public static EnhancedBigtableTableAdminStub createEnhanced( private EnhancedBigtableTableAdminStub( BigtableTableAdminStubSettings settings, ClientContext clientContext, - TableAdminRequestContext requestContext) + @javax.annotation.Nullable TableAdminRequestContext requestContext) throws IOException { super(settings, clientContext); From 6e397230385e0286a644e7ae530d0b09be5caa80 Mon Sep 17 00:00:00 2001 From: cloud-java-bot Date: Wed, 15 Apr 2026 18:39:39 +0000 Subject: [PATCH 02/14] chore: generate libraries at Wed Apr 15 18:37:03 UTC 2026 --- .../admin/v2/models/ConsistencyRequest.java | 29 ++++++++++++++----- .../stub/EnhancedBigtableTableAdminStub.java | 9 ++---- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java index b463669603..7ed8c2d6bb 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java @@ -61,7 +61,10 @@ public static ConsistencyRequest forReplication(String tableId, String consisten Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken, false); + tableId, + CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, + consistencyToken, + false); } public static ConsistencyRequest forDataBoost(String tableId) { @@ -76,17 +79,23 @@ public static ConsistencyRequest forReplicationFromTableName(String tableName) { } @InternalApi - public static ConsistencyRequest forReplicationFromTableName(String tableName, String consistencyToken) { + public static ConsistencyRequest forReplicationFromTableName( + String tableName, String consistencyToken) { Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); return new AutoValue_ConsistencyRequest( - tableName, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken, true); + tableName, + CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, + consistencyToken, + true); } @InternalApi public CheckConsistencyRequest toCheckConsistencyProto( TableAdminRequestContext requestContext, String token) { - Preconditions.checkState(!isFullyQualified(), "Use toCheckConsistencyProto(String token) for fully qualified table names."); + Preconditions.checkState( + !isFullyQualified(), + "Use toCheckConsistencyProto(String token) for fully qualified table names."); CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); @@ -102,7 +111,10 @@ public CheckConsistencyRequest toCheckConsistencyProto( @InternalApi public CheckConsistencyRequest toCheckConsistencyProto(String token) { - Preconditions.checkState(isFullyQualified(), "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table names."); + Preconditions.checkState( + isFullyQualified(), + "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table" + + " names."); CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); if (getMode().equals(CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES)) { @@ -117,7 +129,8 @@ public CheckConsistencyRequest toCheckConsistencyProto(String token) { @InternalApi public GenerateConsistencyTokenRequest toGenerateTokenProto( TableAdminRequestContext requestContext) { - Preconditions.checkState(!isFullyQualified(), "Use toGenerateTokenProto() for fully qualified table names."); + Preconditions.checkState( + !isFullyQualified(), "Use toGenerateTokenProto() for fully qualified table names."); GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); @@ -127,7 +140,9 @@ public GenerateConsistencyTokenRequest toGenerateTokenProto( @InternalApi public GenerateConsistencyTokenRequest toGenerateTokenProto() { - Preconditions.checkState(isFullyQualified(), "Use toGenerateTokenProto(TableAdminRequestContext) for non-qualified table names."); + Preconditions.checkState( + isFullyQualified(), + "Use toGenerateTokenProto(TableAdminRequestContext) for non-qualified table names."); GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); return builder.setName(getTableId()).build(); } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java index 79da312d37..3333529b3b 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java @@ -54,8 +54,7 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final BigtableTableAdminStubSettings settings; private final ClientContext clientContext; - @javax.annotation.Nullable - private final TableAdminRequestContext requestContext; + @javax.annotation.Nullable private final TableAdminRequestContext requestContext; @Deprecated private final AwaitReplicationCallable awaitReplicationCallable; @@ -64,10 +63,8 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { optimizeRestoredTableOperationBaseCallable; public static EnhancedBigtableTableAdminStub createEnhanced( - BigtableTableAdminStubSettings settings) - throws IOException { - return new EnhancedBigtableTableAdminStub( - settings, ClientContext.create(settings), null); + BigtableTableAdminStubSettings settings) throws IOException { + return new EnhancedBigtableTableAdminStub(settings, ClientContext.create(settings), null); } public static EnhancedBigtableTableAdminStub createEnhanced( From 00db638277b28d886a0b92a2593ffa3169547f65 Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Wed, 15 Apr 2026 15:42:17 -0400 Subject: [PATCH 03/14] 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 --- .../v2/BigtableInstanceAdminClientV2.java | 49 +++++ .../admin/v2/BigtableTableAdminClientV2.java | 175 ++++++++++++++++++ .../v2/BigtableInstanceAdminClientV2Test.java | 48 +++++ .../v2/BigtableTableAdminClientV2Test.java | 155 ++++++++++++++++ 4 files changed, 427 insertions(+) create mode 100644 google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java create mode 100644 google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java create mode 100644 google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java create mode 100644 google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java new file mode 100644 index 0000000000..f8284a09c8 --- /dev/null +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java @@ -0,0 +1,49 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2; + +import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; +import java.io.IOException; + +/** + * Modern Cloud Bigtable Instance Admin Client. + * + *

This client extends the auto-generated {@link BaseBigtableInstanceAdminClient} to provide + * manual overrides and additional convenience methods for Critical User Journeys (CUJs) that the + * GAPIC generator cannot handle natively. + */ +public class BigtableInstanceAdminClientV2 extends BaseBigtableInstanceAdminClient { + + protected BigtableInstanceAdminClientV2(BaseBigtableInstanceAdminSettings settings) + throws IOException { + super(settings); + } + + protected BigtableInstanceAdminClientV2(BigtableInstanceAdminStub stub) { + super(stub); + } + + /** Constructs an instance of BigtableInstanceAdminClientV2 with the given settings. */ + public static final BigtableInstanceAdminClientV2 createClient( + BaseBigtableInstanceAdminSettings settings) throws IOException { + return new BigtableInstanceAdminClientV2(settings); + } + + /** Constructs an instance of BigtableInstanceAdminClientV2 with the given stub. */ + public static final BigtableInstanceAdminClientV2 createClient(BigtableInstanceAdminStub stub) { + return new BigtableInstanceAdminClientV2(stub); + } +} diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java new file mode 100644 index 0000000000..75fc8972f2 --- /dev/null +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -0,0 +1,175 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.api.gax.rpc.ApiExceptions; +import com.google.cloud.bigtable.admin.v2.models.ConsistencyRequest; +import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken; +import com.google.cloud.bigtable.admin.v2.models.RestoredTableResult; +import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStub; +import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; +import com.google.common.base.Strings; +import com.google.protobuf.Empty; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +/** + * Modern Cloud Bigtable Table Admin Client. + * + *

This client extends the auto-generated {@link BaseBigtableTableAdminClient} to provide manual + * overrides and additional convenience methods for Critical User Journeys (CUJs) that the GAPIC + * generator cannot handle natively (e.g., chained Long Running Operations, Consistency Polling). + */ +public class BigtableTableAdminClientV2 extends BaseBigtableTableAdminClient { + + protected BigtableTableAdminClientV2(BaseBigtableTableAdminSettings settings) throws IOException { + super(settings); + } + + protected BigtableTableAdminClientV2(BigtableTableAdminStub stub) { + super(stub); + } + + /** Constructs an instance of BigtableTableAdminClientV2 with the given settings. */ + public static final BigtableTableAdminClientV2 createClient(BaseBigtableTableAdminSettings settings) + throws IOException { + // Explicitly create the enhanced stub + EnhancedBigtableTableAdminStub stub = + EnhancedBigtableTableAdminStub.createEnhanced( + (com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings) settings.getStubSettings()); + // Pass the enhanced stub to the existing stub-based constructor + return new BigtableTableAdminClientV2(stub); + } + + /** Constructs an instance of BigtableTableAdminClientV2 with the given stub. */ + public static final BigtableTableAdminClientV2 createClient(BigtableTableAdminStub stub) { + return new BigtableTableAdminClientV2(stub); + } + + /** + * Awaits the completion of the "Optimize Restored Table" operation. + * + *

This method blocks until the restore operation is complete, extracts the optimization token, + * and returns an ApiFuture for the optimization phase. + * + * @param restoreFuture The future returned by restoreTableAsync(). + * @return An ApiFuture that tracks the optimization progress. + */ + public ApiFuture awaitOptimizeRestoredTable(ApiFuture restoreFuture) { + // 1. Block and wait for the restore operation to complete + RestoredTableResult result; + try { + result = restoreFuture.get(); + } catch (Exception e) { + throw new RuntimeException("Restore operation failed", e); + } + + // 2. Extract the operation token from the result + // (RestoredTableResult already wraps the OptimizeRestoredTableOperationToken) + OptimizeRestoredTableOperationToken token = result.getOptimizeRestoredTableOperationToken(); + + if (token == null || Strings.isNullOrEmpty(token.getOperationName())) { + // If there is no optimization operation, return immediate success. + return ApiFutures.immediateFuture(Empty.getDefaultInstance()); + } + + // 3. Return the future for the optimization operation + return ((EnhancedBigtableTableAdminStub) getStub()).awaitOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName()); + } + + /** + * Awaits a restored table is fully optimized. + * + *

Sample code + * + *

{@code
+   * RestoredTableResult result =
+   *     client.restoreTable(RestoreTableRequest.of(clusterId, backupId).setTableId(tableId));
+   * client.awaitOptimizeRestoredTable(result.getOptimizeRestoredTableOperationToken());
+   * }
+ */ + public void awaitOptimizeRestoredTable(OptimizeRestoredTableOperationToken token) + throws ExecutionException, InterruptedException { + awaitOptimizeRestoredTableAsync(token).get(); + } + + /** + * Awaits a restored table is fully optimized asynchronously. + * + *

Sample code + * + *

{@code
+   * RestoredTableResult result =
+   *     client.restoreTable(RestoreTableRequest.of(clusterId, backupId).setTableId(tableId));
+   * ApiFuture future = client.awaitOptimizeRestoredTableAsync(
+   *     result.getOptimizeRestoredTableOperationToken());
+   *
+   * ApiFutures.addCallback(
+   *   future,
+   *   new ApiFutureCallback() {
+   *     public void onSuccess(Void unused) {
+   *       System.out.println("The optimization of the restored table is done.");
+   *     }
+   *
+   *     public void onFailure(Throwable t) {
+   *       t.printStackTrace();
+   *     }
+   *   },
+   *   MoreExecutors.directExecutor()
+   * );
+   * }
+ */ + public ApiFuture awaitOptimizeRestoredTableAsync( + OptimizeRestoredTableOperationToken token) { + ApiFuture emptyFuture = + ((EnhancedBigtableTableAdminStub) getStub()).awaitOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName()); + return ApiFutures.transform( + emptyFuture, + new com.google.api.core.ApiFunction() { + @Override + public Void apply(Empty input) { + return null; + } + }, + com.google.common.util.concurrent.MoreExecutors.directExecutor()); + } + + /** + * Polls an existing consistency token until table replication is consistent across all clusters. + * Useful for checking consistency of a token generated in a separate process. Blocks until + * completion. + * + * @param tableName The fully qualified table name to check. + * @param consistencyToken The token to poll. + */ + public void waitForConsistency(String tableName, String consistencyToken) { + ApiExceptions.callAndTranslateApiException(waitForConsistencyAsync(tableName, consistencyToken)); + } + + /** + * Asynchronously polls the consistency token. Returns a future that completes when table + * replication is consistent across all clusters. + * + * @param tableName The fully qualified table name to check. + * @param consistencyToken The token to poll. + */ + public ApiFuture waitForConsistencyAsync(String tableName, String consistencyToken) { + return ((EnhancedBigtableTableAdminStub) getStub()).awaitConsistencyCallable() + .futureCall(ConsistencyRequest.forReplicationFromTableName(tableName, consistencyToken)); + } +} diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java new file mode 100644 index 0000000000..ef43056272 --- /dev/null +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java @@ -0,0 +1,48 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; + +@RunWith(JUnit4.class) +public class BigtableInstanceAdminClientV2Test { + + @Test + public void testCreateWithStub() { + BigtableInstanceAdminStub mockStub = Mockito.mock(BigtableInstanceAdminStub.class); + BigtableInstanceAdminClientV2 client = BigtableInstanceAdminClientV2.createClient(mockStub); + + assertThat(client).isNotNull(); + } + + @Test + public void testCreateClientWithSettings() throws Exception { + BaseBigtableInstanceAdminSettings settings = + BaseBigtableInstanceAdminSettings.newBuilder() + .setCredentialsProvider(com.google.api.gax.core.NoCredentialsProvider.create()) + .build(); + try (BigtableInstanceAdminClientV2 settingsClient = + BigtableInstanceAdminClientV2.createClient(settings)) { + assertThat(settingsClient).isNotNull(); + } + } +} diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java new file mode 100644 index 0000000000..1eb6c5a4ea --- /dev/null +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java @@ -0,0 +1,155 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.api.gax.longrunning.OperationFuture; +import com.google.api.gax.rpc.OperationCallable; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.bigtable.admin.v2.OptimizeRestoredTableMetadata; +import com.google.cloud.bigtable.admin.v2.models.ConsistencyRequest; +import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken; +import com.google.cloud.bigtable.admin.v2.models.RestoredTableResult; +import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; +import com.google.protobuf.Empty; +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class BigtableTableAdminClientV2Test { + @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); + + private static final String TABLE_NAME = "projects/my-project/instances/my-instance/tables/my-table"; + + @Mock private EnhancedBigtableTableAdminStub mockStub; + + @Mock + private UnaryCallable mockAwaitConsistencyCallable; + + @Mock + private OperationCallable + mockOptimizeRestoredTableCallable; + + private BigtableTableAdminClientV2 client; + + @Before + public void setUp() { + client = BigtableTableAdminClientV2.createClient(mockStub); + } + + @Test + public void testWaitForConsistencyWithToken() { + // Setup + Mockito.when(mockStub.awaitConsistencyCallable()).thenReturn(mockAwaitConsistencyCallable); + + String token = "my-token"; + ConsistencyRequest expectedRequest = ConsistencyRequest.forReplicationFromTableName(TABLE_NAME, token); + + final AtomicBoolean wasCalled = new AtomicBoolean(false); + + Mockito.when(mockAwaitConsistencyCallable.futureCall(expectedRequest)) + .thenAnswer( + (Answer>) + invocationOnMock -> { + wasCalled.set(true); + return ApiFutures.immediateFuture(null); + }); + + // Execute + client.waitForConsistency(TABLE_NAME, token); + + // Verify + assertThat(wasCalled.get()).isTrue(); + } + + @Test + public void testAwaitOptimizeRestoredTable() throws Exception { + // Setup + Mockito.when(mockStub.awaitOptimizeRestoredTableCallable()) + .thenReturn(mockOptimizeRestoredTableCallable); + + String optimizeToken = "my-optimization-token"; + + // 1. Mock the Token + OptimizeRestoredTableOperationToken mockToken = + Mockito.mock(OptimizeRestoredTableOperationToken.class); + Mockito.when(mockToken.getOperationName()).thenReturn(optimizeToken); + + // 2. Mock the Result (wrapping the token) + RestoredTableResult mockResult = Mockito.mock(RestoredTableResult.class); + Mockito.when(mockResult.getOptimizeRestoredTableOperationToken()).thenReturn(mockToken); + + // 3. Mock the Input Future (returning the result) + ApiFuture mockRestoreFuture = Mockito.mock(ApiFuture.class); + Mockito.when(mockRestoreFuture.get()).thenReturn(mockResult); + + // 4. Mock the Stub's behavior (resuming the Optimize Op) + OperationFuture mockOptimizeOp = + Mockito.mock(OperationFuture.class); + Mockito.when(mockOptimizeRestoredTableCallable.resumeFutureCall(optimizeToken)) + .thenReturn(mockOptimizeOp); + + // Execute + ApiFuture result = client.awaitOptimizeRestoredTable(mockRestoreFuture); + + // Verify + assertThat(result).isEqualTo(mockOptimizeOp); + Mockito.verify(mockOptimizeRestoredTableCallable).resumeFutureCall(optimizeToken); + } + + @Test + public void testAwaitOptimizeRestoredTable_NoOp() throws Exception { + // Setup: Result with NO optimization token (null or empty) + RestoredTableResult mockResult = Mockito.mock(RestoredTableResult.class); + Mockito.when(mockResult.getOptimizeRestoredTableOperationToken()).thenReturn(null); + + // Mock the Input Future + ApiFuture mockRestoreFuture = Mockito.mock(ApiFuture.class); + Mockito.when(mockRestoreFuture.get()).thenReturn(mockResult); + + // Execute + ApiFuture result = client.awaitOptimizeRestoredTable(mockRestoreFuture); + + // Verify: Returns immediate success (Empty) without calling the stub + assertThat(result.get()).isEqualTo(Empty.getDefaultInstance()); + } + + @Test + public void testCreateClientWithSettings() throws Exception { + BaseBigtableTableAdminSettings settings = + BaseBigtableTableAdminSettings.newBuilder() + .setCredentialsProvider(com.google.api.gax.core.NoCredentialsProvider.create()) + .build(); + try (BigtableTableAdminClientV2 settingsClient = + BigtableTableAdminClientV2.createClient(settings)) { + // Verify that the underlying stub was correctly instantiated as the Enhanced stub + // so that downcasts in the CUJs do not throw a ClassCastException. + assertThat(settingsClient.getStub()).isInstanceOf(EnhancedBigtableTableAdminStub.class); + } + } +} From ccdee5dc565602a4da9d25ae1ea563527ab405bf Mon Sep 17 00:00:00 2001 From: cloud-java-bot Date: Wed, 15 Apr 2026 20:15:28 +0000 Subject: [PATCH 04/14] chore: generate libraries at Wed Apr 15 20:12:56 UTC 2026 --- .../admin/v2/BigtableTableAdminClientV2.java | 21 +++++++++----- .../admin/v2/models/ConsistencyRequest.java | 29 ++++++++++++++----- .../stub/EnhancedBigtableTableAdminStub.java | 9 ++---- .../v2/BigtableInstanceAdminClientV2Test.java | 2 +- .../v2/BigtableTableAdminClientV2Test.java | 9 +++--- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java index 75fc8972f2..03f0dfb49c 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -46,12 +46,13 @@ protected BigtableTableAdminClientV2(BigtableTableAdminStub stub) { } /** Constructs an instance of BigtableTableAdminClientV2 with the given settings. */ - public static final BigtableTableAdminClientV2 createClient(BaseBigtableTableAdminSettings settings) - throws IOException { + public static final BigtableTableAdminClientV2 createClient( + BaseBigtableTableAdminSettings settings) throws IOException { // Explicitly create the enhanced stub EnhancedBigtableTableAdminStub stub = EnhancedBigtableTableAdminStub.createEnhanced( - (com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings) settings.getStubSettings()); + (com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings) + settings.getStubSettings()); // Pass the enhanced stub to the existing stub-based constructor return new BigtableTableAdminClientV2(stub); } @@ -89,7 +90,9 @@ public ApiFuture awaitOptimizeRestoredTable(ApiFuture awaitOptimizeRestoredTableAsync( OptimizeRestoredTableOperationToken token) { ApiFuture emptyFuture = - ((EnhancedBigtableTableAdminStub) getStub()).awaitOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName()); + ((EnhancedBigtableTableAdminStub) getStub()) + .awaitOptimizeRestoredTableCallable() + .resumeFutureCall(token.getOperationName()); return ApiFutures.transform( emptyFuture, new com.google.api.core.ApiFunction() { @@ -158,7 +163,8 @@ public Void apply(Empty input) { * @param consistencyToken The token to poll. */ public void waitForConsistency(String tableName, String consistencyToken) { - ApiExceptions.callAndTranslateApiException(waitForConsistencyAsync(tableName, consistencyToken)); + ApiExceptions.callAndTranslateApiException( + waitForConsistencyAsync(tableName, consistencyToken)); } /** @@ -169,7 +175,8 @@ public void waitForConsistency(String tableName, String consistencyToken) { * @param consistencyToken The token to poll. */ public ApiFuture waitForConsistencyAsync(String tableName, String consistencyToken) { - return ((EnhancedBigtableTableAdminStub) getStub()).awaitConsistencyCallable() + return ((EnhancedBigtableTableAdminStub) getStub()) + .awaitConsistencyCallable() .futureCall(ConsistencyRequest.forReplicationFromTableName(tableName, consistencyToken)); } } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java index b463669603..7ed8c2d6bb 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java @@ -61,7 +61,10 @@ public static ConsistencyRequest forReplication(String tableId, String consisten Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken, false); + tableId, + CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, + consistencyToken, + false); } public static ConsistencyRequest forDataBoost(String tableId) { @@ -76,17 +79,23 @@ public static ConsistencyRequest forReplicationFromTableName(String tableName) { } @InternalApi - public static ConsistencyRequest forReplicationFromTableName(String tableName, String consistencyToken) { + public static ConsistencyRequest forReplicationFromTableName( + String tableName, String consistencyToken) { Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); return new AutoValue_ConsistencyRequest( - tableName, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken, true); + tableName, + CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, + consistencyToken, + true); } @InternalApi public CheckConsistencyRequest toCheckConsistencyProto( TableAdminRequestContext requestContext, String token) { - Preconditions.checkState(!isFullyQualified(), "Use toCheckConsistencyProto(String token) for fully qualified table names."); + Preconditions.checkState( + !isFullyQualified(), + "Use toCheckConsistencyProto(String token) for fully qualified table names."); CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); @@ -102,7 +111,10 @@ public CheckConsistencyRequest toCheckConsistencyProto( @InternalApi public CheckConsistencyRequest toCheckConsistencyProto(String token) { - Preconditions.checkState(isFullyQualified(), "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table names."); + Preconditions.checkState( + isFullyQualified(), + "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table" + + " names."); CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); if (getMode().equals(CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES)) { @@ -117,7 +129,8 @@ public CheckConsistencyRequest toCheckConsistencyProto(String token) { @InternalApi public GenerateConsistencyTokenRequest toGenerateTokenProto( TableAdminRequestContext requestContext) { - Preconditions.checkState(!isFullyQualified(), "Use toGenerateTokenProto() for fully qualified table names."); + Preconditions.checkState( + !isFullyQualified(), "Use toGenerateTokenProto() for fully qualified table names."); GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); @@ -127,7 +140,9 @@ public GenerateConsistencyTokenRequest toGenerateTokenProto( @InternalApi public GenerateConsistencyTokenRequest toGenerateTokenProto() { - Preconditions.checkState(isFullyQualified(), "Use toGenerateTokenProto(TableAdminRequestContext) for non-qualified table names."); + Preconditions.checkState( + isFullyQualified(), + "Use toGenerateTokenProto(TableAdminRequestContext) for non-qualified table names."); GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); return builder.setName(getTableId()).build(); } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java index 79da312d37..3333529b3b 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java @@ -54,8 +54,7 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final BigtableTableAdminStubSettings settings; private final ClientContext clientContext; - @javax.annotation.Nullable - private final TableAdminRequestContext requestContext; + @javax.annotation.Nullable private final TableAdminRequestContext requestContext; @Deprecated private final AwaitReplicationCallable awaitReplicationCallable; @@ -64,10 +63,8 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { optimizeRestoredTableOperationBaseCallable; public static EnhancedBigtableTableAdminStub createEnhanced( - BigtableTableAdminStubSettings settings) - throws IOException { - return new EnhancedBigtableTableAdminStub( - settings, ClientContext.create(settings), null); + BigtableTableAdminStubSettings settings) throws IOException { + return new EnhancedBigtableTableAdminStub(settings, ClientContext.create(settings), null); } public static EnhancedBigtableTableAdminStub createEnhanced( diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java index ef43056272..7abf4941a6 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java @@ -30,7 +30,7 @@ public class BigtableInstanceAdminClientV2Test { public void testCreateWithStub() { BigtableInstanceAdminStub mockStub = Mockito.mock(BigtableInstanceAdminStub.class); BigtableInstanceAdminClientV2 client = BigtableInstanceAdminClientV2.createClient(mockStub); - + assertThat(client).isNotNull(); } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java index 1eb6c5a4ea..4f7a3fcb0b 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java @@ -44,12 +44,12 @@ public class BigtableTableAdminClientV2Test { @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - private static final String TABLE_NAME = "projects/my-project/instances/my-instance/tables/my-table"; + private static final String TABLE_NAME = + "projects/my-project/instances/my-instance/tables/my-table"; @Mock private EnhancedBigtableTableAdminStub mockStub; - @Mock - private UnaryCallable mockAwaitConsistencyCallable; + @Mock private UnaryCallable mockAwaitConsistencyCallable; @Mock private OperationCallable @@ -68,7 +68,8 @@ public void testWaitForConsistencyWithToken() { Mockito.when(mockStub.awaitConsistencyCallable()).thenReturn(mockAwaitConsistencyCallable); String token = "my-token"; - ConsistencyRequest expectedRequest = ConsistencyRequest.forReplicationFromTableName(TABLE_NAME, token); + ConsistencyRequest expectedRequest = + ConsistencyRequest.forReplicationFromTableName(TABLE_NAME, token); final AtomicBoolean wasCalled = new AtomicBoolean(false); From bff60a6d403da773c88642d23be9672bfa9c131e Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Fri, 17 Apr 2026 10:54:10 -0400 Subject: [PATCH 05/14] PR feedback --- .../admin/v2/BigtableTableAdminClientV2.java | 184 ++++++++++++++++-- .../v2/stub/AwaitConsistencyCallable.java | 6 +- .../v2/BigtableTableAdminClientV2Test.java | 6 +- 3 files changed, 174 insertions(+), 22 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java index 03f0dfb49c..fa61757095 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -15,18 +15,40 @@ */ package com.google.cloud.bigtable.admin.v2; +import com.google.api.core.ApiFunction; import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; +import com.google.api.gax.grpc.GrpcCallSettings; +import com.google.api.gax.grpc.GrpcCallableFactory; +import com.google.api.gax.grpc.ProtoOperationTransformers.MetadataTransformer; +import com.google.api.gax.grpc.ProtoOperationTransformers.ResponseTransformer; +import com.google.api.gax.longrunning.OperationSnapshot; +import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; +import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.ApiExceptions; +import com.google.api.gax.rpc.ClientContext; +import com.google.api.gax.rpc.OperationCallSettings; +import com.google.api.gax.rpc.OperationCallable; +import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.bigtable.admin.v2.OptimizeRestoredTableMetadata; import com.google.cloud.bigtable.admin.v2.models.ConsistencyRequest; import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken; import com.google.cloud.bigtable.admin.v2.models.RestoredTableResult; +import com.google.cloud.bigtable.admin.v2.stub.AwaitConsistencyCallable; import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStub; -import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; +import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; import com.google.common.base.Strings; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.longrunning.Operation; import com.google.protobuf.Empty; +import io.grpc.MethodDescriptor; +import io.grpc.MethodDescriptor.Marshaller; +import io.grpc.MethodDescriptor.MethodType; import java.io.IOException; +import java.io.InputStream; import java.util.concurrent.ExecutionException; +import org.threeten.bp.Duration; /** * Modern Cloud Bigtable Table Admin Client. @@ -36,25 +58,135 @@ * generator cannot handle natively (e.g., chained Long Running Operations, Consistency Polling). */ public class BigtableTableAdminClientV2 extends BaseBigtableTableAdminClient { + private final AwaitConsistencyCallable awaitConsistencyCallable; + private final OperationCallable + optimizeRestoredTableOperationBaseCallable; protected BigtableTableAdminClientV2(BaseBigtableTableAdminSettings settings) throws IOException { super(settings); + this.awaitConsistencyCallable = + createAwaitConsistencyCallable((BigtableTableAdminStubSettings) settings.getStubSettings()); + this.optimizeRestoredTableOperationBaseCallable = + createOptimizeRestoredTableOperationBaseCallable( + (BigtableTableAdminStubSettings) settings.getStubSettings()); } protected BigtableTableAdminClientV2(BigtableTableAdminStub stub) { super(stub); + this.awaitConsistencyCallable = null; + this.optimizeRestoredTableOperationBaseCallable = null; + } + + private AwaitConsistencyCallable createAwaitConsistencyCallable( + BigtableTableAdminStubSettings settings) throws IOException { + ClientContext clientContext = ClientContext.create(settings); + // TODO(igorbernstein2): expose polling settings + RetrySettings pollingSettings = + RetrySettings.newBuilder() + .setTotalTimeout( + settings.checkConsistencySettings().getRetrySettings().getTotalTimeout()) + .setInitialRetryDelay(Duration.ofSeconds(10)) + .setRetryDelayMultiplier(1.0) + .setMaxRetryDelay(Duration.ofSeconds(10)) + .setInitialRpcTimeout(Duration.ZERO) + .setMaxRpcTimeout(Duration.ZERO) + .setRpcTimeoutMultiplier(1.0) + .build(); + + return AwaitConsistencyCallable.create( + getStub().generateConsistencyTokenCallable(), + getStub().checkConsistencyCallable(), + clientContext, + pollingSettings); + } + + private OperationCallable + createOptimizeRestoredTableOperationBaseCallable(BigtableTableAdminStubSettings settings) + throws IOException { + ClientContext clientContext = ClientContext.create(settings); + + GrpcCallSettings unusedInitialCallSettings = + GrpcCallSettings.create( + MethodDescriptor.newBuilder() + .setType(MethodType.UNARY) + .setFullMethodName( + "google.bigtable.admin.v2.BigtableTableAdmin/OptimizeRestoredTable") + .setRequestMarshaller( + new Marshaller() { + @Override + public InputStream stream(Void value) { + throw new UnsupportedOperationException("not used"); + } + + @Override + public Void parse(InputStream stream) { + throw new UnsupportedOperationException("not used"); + } + }) + .setResponseMarshaller( + new Marshaller() { + @Override + public InputStream stream(Operation value) { + throw new UnsupportedOperationException("not used"); + } + + @Override + public Operation parse(InputStream stream) { + throw new UnsupportedOperationException("not used"); + } + }) + .build()); + + final MetadataTransformer protoMetadataTransformer = + MetadataTransformer.create(OptimizeRestoredTableMetadata.class); + + final ResponseTransformer protoResponseTransformer = + ResponseTransformer.create(com.google.protobuf.Empty.class); + + OperationCallSettings operationCallSettings = + OperationCallSettings.newBuilder() + .setInitialCallSettings( + UnaryCallSettings.newUnaryCallSettingsBuilder() + .setSimpleTimeoutNoRetries(Duration.ZERO) + .build()) + .setMetadataTransformer( + new ApiFunction() { + @Override + public OptimizeRestoredTableMetadata apply(OperationSnapshot input) { + return protoMetadataTransformer.apply(input); + } + }) + .setResponseTransformer( + new ApiFunction() { + @Override + public Empty apply(OperationSnapshot input) { + return protoResponseTransformer.apply(input); + } + }) + .setPollingAlgorithm( + OperationTimedPollAlgorithm.create( + RetrySettings.newBuilder() + .setInitialRetryDelay(Duration.ofMillis(500L)) + .setRetryDelayMultiplier(1.5) + .setMaxRetryDelay(Duration.ofMillis(5000L)) + .setInitialRpcTimeout(Duration.ZERO) + .setRpcTimeoutMultiplier(1.0) + .setMaxRpcTimeout(Duration.ZERO) + .setTotalTimeout(Duration.ofMillis(600000L)) + .build())) + .build(); + + return GrpcCallableFactory.createOperationCallable( + unusedInitialCallSettings, + operationCallSettings, + clientContext, + getStub().getOperationsStub()); } /** Constructs an instance of BigtableTableAdminClientV2 with the given settings. */ public static final BigtableTableAdminClientV2 createClient( BaseBigtableTableAdminSettings settings) throws IOException { - // Explicitly create the enhanced stub - EnhancedBigtableTableAdminStub stub = - EnhancedBigtableTableAdminStub.createEnhanced( - (com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings) - settings.getStubSettings()); - // Pass the enhanced stub to the existing stub-based constructor - return new BigtableTableAdminClientV2(stub); + return new BigtableTableAdminClientV2(settings); } /** Constructs an instance of BigtableTableAdminClientV2 with the given stub. */ @@ -90,9 +222,7 @@ public ApiFuture awaitOptimizeRestoredTable(ApiFuture awaitOptimizeRestoredTableAsync( OptimizeRestoredTableOperationToken token) { ApiFuture emptyFuture = - ((EnhancedBigtableTableAdminStub) getStub()) - .awaitOptimizeRestoredTableCallable() - .resumeFutureCall(token.getOperationName()); + getOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName()); return ApiFutures.transform( emptyFuture, new com.google.api.core.ApiFunction() { @@ -175,8 +303,32 @@ public void waitForConsistency(String tableName, String consistencyToken) { * @param consistencyToken The token to poll. */ public ApiFuture waitForConsistencyAsync(String tableName, String consistencyToken) { - return ((EnhancedBigtableTableAdminStub) getStub()) - .awaitConsistencyCallable() + return getAwaitConsistencyCallable() .futureCall(ConsistencyRequest.forReplicationFromTableName(tableName, consistencyToken)); } + + private UnaryCallable getAwaitConsistencyCallable() { + if (awaitConsistencyCallable != null) { + return awaitConsistencyCallable; + } + // Fallback for tests or stub-based initialization + if (getStub() instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { + return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) + .awaitConsistencyCallable(); + } + throw new IllegalStateException("AwaitConsistencyCallable not initialized."); + } + + private OperationCallable + getOptimizeRestoredTableCallable() { + if (optimizeRestoredTableOperationBaseCallable != null) { + return optimizeRestoredTableOperationBaseCallable; + } + // Fallback for tests or stub-based initialization + if (getStub() instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { + return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) + .awaitOptimizeRestoredTableCallable(); + } + throw new IllegalStateException("OptimizeRestoredTableCallable not initialized."); + } } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java index a8ccdd9704..f772421b8d 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java @@ -51,7 +51,7 @@ *

This callable wraps GenerateConsistencyToken and CheckConsistency RPCs. It will generate a * token then poll until isConsistent is true. */ -class AwaitConsistencyCallable extends UnaryCallable { +public class AwaitConsistencyCallable extends UnaryCallable { private final UnaryCallable generateCallable; private final UnaryCallable checkCallable; @@ -59,7 +59,7 @@ class AwaitConsistencyCallable extends UnaryCallable { @Nullable private final TableAdminRequestContext requestContext; - static AwaitConsistencyCallable create( + public static AwaitConsistencyCallable create( UnaryCallable generateCallable, UnaryCallable checkCallable, @@ -79,7 +79,7 @@ static AwaitConsistencyCallable create( generateCallable, checkCallable, retryingExecutor, requestContext); } - static AwaitConsistencyCallable create( + public static AwaitConsistencyCallable create( UnaryCallable generateCallable, UnaryCallable checkCallable, diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java index 4f7a3fcb0b..0334f72201 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java @@ -148,9 +148,9 @@ public void testCreateClientWithSettings() throws Exception { .build(); try (BigtableTableAdminClientV2 settingsClient = BigtableTableAdminClientV2.createClient(settings)) { - // Verify that the underlying stub was correctly instantiated as the Enhanced stub - // so that downcasts in the CUJs do not throw a ClassCastException. - assertThat(settingsClient.getStub()).isInstanceOf(EnhancedBigtableTableAdminStub.class); + // Verify that the underlying stub is NOT an Enhanced stub by default + // but the client has successfully initialized its own callables. + assertThat(settingsClient.getStub()).isNotInstanceOf(EnhancedBigtableTableAdminStub.class); } } } From d3688251e19d528c290ab47e390c230f42550f04 Mon Sep 17 00:00:00 2001 From: cloud-java-bot Date: Fri, 17 Apr 2026 14:58:36 +0000 Subject: [PATCH 06/14] chore: generate libraries at Fri Apr 17 14:55:58 UTC 2026 --- .../bigtable/admin/v2/BigtableTableAdminClientV2.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java index fa61757095..7749b3ca3f 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -39,7 +39,6 @@ import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStub; import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; import com.google.common.base.Strings; -import com.google.common.util.concurrent.MoreExecutors; import com.google.longrunning.Operation; import com.google.protobuf.Empty; import io.grpc.MethodDescriptor; @@ -312,7 +311,8 @@ private UnaryCallable getAwaitConsistencyCallable() { return awaitConsistencyCallable; } // Fallback for tests or stub-based initialization - if (getStub() instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { + if (getStub() + instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) .awaitConsistencyCallable(); } @@ -325,7 +325,8 @@ private UnaryCallable getAwaitConsistencyCallable() { return optimizeRestoredTableOperationBaseCallable; } // Fallback for tests or stub-based initialization - if (getStub() instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { + if (getStub() + instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) .awaitOptimizeRestoredTableCallable(); } From 392717f18a22f3aaeeaca1ce2ff931e4606007ef Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Fri, 17 Apr 2026 12:30:41 -0400 Subject: [PATCH 07/14] PR comment 2 --- .../admin/v2/BigtableTableAdminClientV2.java | 21 ++++++++++++------- .../v2/BigtableTableAdminClientV2Test.java | 13 ++++++------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java index 7749b3ca3f..52b439a01d 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -76,6 +76,17 @@ protected BigtableTableAdminClientV2(BigtableTableAdminStub stub) { this.optimizeRestoredTableOperationBaseCallable = null; } + @com.google.common.annotations.VisibleForTesting + BigtableTableAdminClientV2( + BigtableTableAdminStub stub, + AwaitConsistencyCallable awaitConsistencyCallable, + OperationCallable + optimizeRestoredTableOperationBaseCallable) { + super(stub); + this.awaitConsistencyCallable = awaitConsistencyCallable; + this.optimizeRestoredTableOperationBaseCallable = optimizeRestoredTableOperationBaseCallable; + } + private AwaitConsistencyCallable createAwaitConsistencyCallable( BigtableTableAdminStubSettings settings) throws IOException { ClientContext clientContext = ClientContext.create(settings); @@ -324,12 +335,8 @@ private UnaryCallable getAwaitConsistencyCallable() { if (optimizeRestoredTableOperationBaseCallable != null) { return optimizeRestoredTableOperationBaseCallable; } - // Fallback for tests or stub-based initialization - if (getStub() - instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { - return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) - .awaitOptimizeRestoredTableCallable(); - } - throw new IllegalStateException("OptimizeRestoredTableCallable not initialized."); + throw new IllegalStateException( + "OptimizeRestoredTableCallable not initialized. BigtableTableAdminClientV2 must be " + + "initialized via settings to use this functionality."); } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java index 0334f72201..a8d919e1e3 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java @@ -26,6 +26,8 @@ import com.google.cloud.bigtable.admin.v2.models.ConsistencyRequest; import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken; import com.google.cloud.bigtable.admin.v2.models.RestoredTableResult; +import com.google.cloud.bigtable.admin.v2.stub.AwaitConsistencyCallable; +import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStub; import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; import com.google.protobuf.Empty; import java.util.concurrent.atomic.AtomicBoolean; @@ -47,9 +49,9 @@ public class BigtableTableAdminClientV2Test { private static final String TABLE_NAME = "projects/my-project/instances/my-instance/tables/my-table"; - @Mock private EnhancedBigtableTableAdminStub mockStub; + @Mock private BigtableTableAdminStub mockStub; - @Mock private UnaryCallable mockAwaitConsistencyCallable; + @Mock private AwaitConsistencyCallable mockAwaitConsistencyCallable; @Mock private OperationCallable @@ -59,13 +61,14 @@ public class BigtableTableAdminClientV2Test { @Before public void setUp() { - client = BigtableTableAdminClientV2.createClient(mockStub); + client = + new BigtableTableAdminClientV2( + mockStub, mockAwaitConsistencyCallable, mockOptimizeRestoredTableCallable); } @Test public void testWaitForConsistencyWithToken() { // Setup - Mockito.when(mockStub.awaitConsistencyCallable()).thenReturn(mockAwaitConsistencyCallable); String token = "my-token"; ConsistencyRequest expectedRequest = @@ -91,8 +94,6 @@ public void testWaitForConsistencyWithToken() { @Test public void testAwaitOptimizeRestoredTable() throws Exception { // Setup - Mockito.when(mockStub.awaitOptimizeRestoredTableCallable()) - .thenReturn(mockOptimizeRestoredTableCallable); String optimizeToken = "my-optimization-token"; From ed4476a09476b610e409f9c01bf0ec09bcaf83af Mon Sep 17 00:00:00 2001 From: cloud-java-bot Date: Fri, 17 Apr 2026 16:34:31 +0000 Subject: [PATCH 08/14] chore: generate libraries at Fri Apr 17 16:31:54 UTC 2026 --- .../cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java | 1 - 1 file changed, 1 deletion(-) diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java index a8d919e1e3..104088d2b3 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java @@ -21,7 +21,6 @@ import com.google.api.core.ApiFutures; import com.google.api.gax.longrunning.OperationFuture; import com.google.api.gax.rpc.OperationCallable; -import com.google.api.gax.rpc.UnaryCallable; import com.google.bigtable.admin.v2.OptimizeRestoredTableMetadata; import com.google.cloud.bigtable.admin.v2.models.ConsistencyRequest; import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken; From 95f4d32dcd6151dbbc6fb0af649f0f9ceebc011a Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Fri, 17 Apr 2026 12:47:06 -0400 Subject: [PATCH 09/14] PR feedback 3 --- .../bigtable/admin/v2/BigtableTableAdminClientV2.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java index 52b439a01d..f61f2f0904 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -321,13 +321,9 @@ private UnaryCallable getAwaitConsistencyCallable() { if (awaitConsistencyCallable != null) { return awaitConsistencyCallable; } - // Fallback for tests or stub-based initialization - if (getStub() - instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { - return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) - .awaitConsistencyCallable(); - } - throw new IllegalStateException("AwaitConsistencyCallable not initialized."); + throw new IllegalStateException( + "AwaitConsistencyCallable not initialized. BigtableTableAdminClientV2 must be " + + "initialized via settings to use this functionality."); } private OperationCallable From 78dad41ad1f4f85df1fb428a961547ca068a29aa Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Thu, 23 Apr 2026 10:57:42 -0400 Subject: [PATCH 10/14] restore files --- .../admin/v2/models/ConsistencyRequest.java | 102 +----------------- .../v2/stub/AwaitConsistencyCallable.java | 38 ++----- .../stub/EnhancedBigtableTableAdminStub.java | 33 +----- 3 files changed, 17 insertions(+), 156 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java index d8ffb69e12..f338776503 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java @@ -43,11 +43,9 @@ public abstract class ConsistencyRequest { @Nullable public abstract String getConsistencyToken(); - protected abstract boolean isFullyQualified(); - public static ConsistencyRequest forReplication(String tableId) { return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null, false); + tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null); } /** @@ -61,127 +59,37 @@ public static ConsistencyRequest forReplication(String tableId, String consisten Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); return new AutoValue_ConsistencyRequest( - tableId, - CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, - consistencyToken, - false); + tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken); } public static ConsistencyRequest forDataBoost(String tableId) { return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.DATA_BOOST_READ_LOCAL_WRITES, null, false); - } - - @InternalApi - public static ConsistencyRequest forReplicationFromTableName(String tableName) { - Preconditions.checkArgument( - TableName.isParsableFrom(tableName), "tableName must be a fully qualified table name"); - return new AutoValue_ConsistencyRequest( - tableName, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null, true); + tableId, CheckConsistencyRequest.ModeCase.DATA_BOOST_READ_LOCAL_WRITES, null); } - @InternalApi - public static ConsistencyRequest forReplicationFromTableName( - String tableName, String consistencyToken) { - Preconditions.checkArgument( - TableName.isParsableFrom(tableName), "tableName must be a fully qualified table name"); - Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); - - return new AutoValue_ConsistencyRequest( - tableName, - CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, - consistencyToken, - true); - } - - private CheckConsistencyRequest.Builder buildBaseRequest(String name, String token) { - CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); - - if (getMode().equals(CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES)) { - builder.setStandardReadRemoteWrites(StandardReadRemoteWrites.newBuilder().build()); - } else { - builder.setDataBoostReadLocalWrites(DataBoostReadLocalWrites.newBuilder().build()); - } - - return builder.setName(name).setConsistencyToken(token); - } - - /** - * Creates a CheckConsistencyRequest proto. This variant is used when the ConsistencyRequest was - * initialized with a short table ID, relying on the TableAdminRequestContext to construct the - * fully qualified table name. - */ @InternalApi public CheckConsistencyRequest toCheckConsistencyProto( TableAdminRequestContext requestContext, String token) { - Preconditions.checkState( - !isFullyQualified(), - "Use toCheckConsistencyProto(String token) for fully qualified table names."); + CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); - return buildBaseRequest(tableName.toString(), token).build(); - } - - /** - * Creates a CheckConsistencyRequest proto. This variant is used when the ConsistencyRequest was - * initialized with a fully qualified table name, eliminating the need for a request context. - */ - @InternalApi - public CheckConsistencyRequest toCheckConsistencyProto(String token) { - Preconditions.checkState( - isFullyQualified(), - "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table" - + " names."); - - return buildBaseRequest(getTableId(), token).build(); - } - - /** - * Creates a GenerateConsistencyTokenRequest proto. This variant is used when the - * ConsistencyRequest was initialized with a short table ID, relying on the - * TableAdminRequestContext to construct the fully qualified table name. - */ - @InternalApi - public CheckConsistencyRequest toCheckConsistencyProto(String token) { - Preconditions.checkState( - isFullyQualified(), - "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table" - + " names."); - CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); - if (getMode().equals(CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES)) { builder.setStandardReadRemoteWrites(StandardReadRemoteWrites.newBuilder().build()); } else { builder.setDataBoostReadLocalWrites(DataBoostReadLocalWrites.newBuilder().build()); } - return builder.setName(getTableId()).setConsistencyToken(token).build(); + return builder.setName(tableName.toString()).setConsistencyToken(token).build(); } @InternalApi public GenerateConsistencyTokenRequest toGenerateTokenProto( TableAdminRequestContext requestContext) { - Preconditions.checkState( - !isFullyQualified(), "Use toGenerateTokenProto() for fully qualified table names."); GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); return builder.setName(tableName.toString()).build(); } - - /** - * Creates a GenerateConsistencyTokenRequest proto. This variant is used when the - * ConsistencyRequest was initialized with a fully qualified table name, eliminating the need for - * a request context. - */ - @InternalApi - public GenerateConsistencyTokenRequest toGenerateTokenProto() { - Preconditions.checkState( - isFullyQualified(), - "Use toGenerateTokenProto(TableAdminRequestContext) for non-qualified table names."); - GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); - return builder.setName(getTableId()).build(); - } } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java index 01c6a81225..b4e42e2354 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java @@ -42,7 +42,6 @@ import com.google.common.util.concurrent.MoreExecutors; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; -import javax.annotation.Nullable; /** * Callable that waits until either replication or Data Boost has caught up to the point it was @@ -51,21 +50,21 @@ *

This callable wraps GenerateConsistencyToken and CheckConsistency RPCs. It will generate a * token then poll until isConsistent is true. */ -public class AwaitConsistencyCallable extends UnaryCallable { +class AwaitConsistencyCallable extends UnaryCallable { private final UnaryCallable generateCallable; private final UnaryCallable checkCallable; private final RetryingExecutor executor; - @Nullable private final TableAdminRequestContext requestContext; + private final TableAdminRequestContext requestContext; - public static AwaitConsistencyCallable create( + static AwaitConsistencyCallable create( UnaryCallable generateCallable, UnaryCallable checkCallable, ClientContext clientContext, RetrySettings pollingSettings, - @Nullable TableAdminRequestContext requestContext) { + TableAdminRequestContext requestContext) { RetryAlgorithm retryAlgorithm = new RetryAlgorithm<>( @@ -79,22 +78,13 @@ public static AwaitConsistencyCallable create( generateCallable, checkCallable, retryingExecutor, requestContext); } - static AwaitConsistencyCallable create( - UnaryCallable - generateCallable, - UnaryCallable checkCallable, - ClientContext clientContext, - RetrySettings pollingSettings) { - return create(generateCallable, checkCallable, clientContext, pollingSettings, null); - } - @VisibleForTesting AwaitConsistencyCallable( UnaryCallable generateCallable, UnaryCallable checkCallable, RetryingExecutor executor, - @Nullable TableAdminRequestContext requestContext) { + TableAdminRequestContext requestContext) { this.generateCallable = generateCallable; this.checkCallable = checkCallable; this.executor = executor; @@ -108,19 +98,13 @@ public ApiFuture futureCall( // If the token is already provided, skip generation and poll directly. if (consistencyRequest.getConsistencyToken() != null) { CheckConsistencyRequest request = - requestContext == null - ? consistencyRequest.toCheckConsistencyProto(consistencyRequest.getConsistencyToken()) - : consistencyRequest.toCheckConsistencyProto( - requestContext, consistencyRequest.getConsistencyToken()); + consistencyRequest.toCheckConsistencyProto( + requestContext, consistencyRequest.getConsistencyToken()); return pollToken(request, apiCallContext); } ApiFuture tokenFuture = - generateToken( - requestContext == null - ? consistencyRequest.toGenerateTokenProto() - : consistencyRequest.toGenerateTokenProto(requestContext), - apiCallContext); + generateToken(consistencyRequest.toGenerateTokenProto(requestContext), apiCallContext); return ApiFutures.transformAsync( tokenFuture, @@ -128,10 +112,8 @@ public ApiFuture futureCall( @Override public ApiFuture apply(GenerateConsistencyTokenResponse input) { CheckConsistencyRequest request = - requestContext == null - ? consistencyRequest.toCheckConsistencyProto(input.getConsistencyToken()) - : consistencyRequest.toCheckConsistencyProto( - requestContext, input.getConsistencyToken()); + consistencyRequest.toCheckConsistencyProto( + requestContext, input.getConsistencyToken()); return pollToken(request, apiCallContext); } }, diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java index 5b3b87383d..e68cafca54 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java @@ -54,7 +54,7 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final BigtableTableAdminStubSettings settings; private final ClientContext clientContext; - @javax.annotation.Nullable private final TableAdminRequestContext requestContext; + private final TableAdminRequestContext requestContext; @Deprecated private final AwaitReplicationCallable awaitReplicationCallable; @@ -62,35 +62,6 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final OperationCallable optimizeRestoredTableOperationBaseCallable; - /** - * Creates an instance of {@link EnhancedBigtableTableAdminStub} using the provided settings. This - * variant is used by the V2 client stack which relies on fully qualified table names and - * therefore does not require a {@link TableAdminRequestContext}. - * - * @param settings The settings used to configure the stub. - * @return A new instance of {@code EnhancedBigtableTableAdminStub}. - * @throws IOException If there are errors creating the underlying client context. - */ - public static EnhancedBigtableTableAdminStub createEnhanced( - BigtableTableAdminStubSettings settings) throws IOException { - return new EnhancedBigtableTableAdminStub(settings, ClientContext.create(settings), null); - } - - /** - * Creates an instance of {@link EnhancedBigtableTableAdminStub} using the provided settings. This - * variant is used by the legacy client stack which relies on short table IDs and requires a - * {@link TableAdminRequestContext} to construct fully qualified table names. - * - * @param settings The settings used to configure the stub. - * @param requestContext The context used to format short table IDs. - * @return A new instance of {@code EnhancedBigtableTableAdminStub}. - * @throws IOException If there are errors creating the underlying client context. - */ - public static EnhancedBigtableTableAdminStub createEnhanced( - BigtableTableAdminStubSettings settings) throws IOException { - return new EnhancedBigtableTableAdminStub(settings, ClientContext.create(settings), null); - } - public static EnhancedBigtableTableAdminStub createEnhanced( BigtableTableAdminStubSettings settings, TableAdminRequestContext requestContext) throws IOException { @@ -101,7 +72,7 @@ public static EnhancedBigtableTableAdminStub createEnhanced( private EnhancedBigtableTableAdminStub( BigtableTableAdminStubSettings settings, ClientContext clientContext, - @javax.annotation.Nullable TableAdminRequestContext requestContext) + TableAdminRequestContext requestContext) throws IOException { super(settings, clientContext); From 7abd5cb1077e72a7494ee79ff7d03ef38836fa73 Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Thu, 23 Apr 2026 11:42:46 -0400 Subject: [PATCH 11/14] restore files --- .../admin/v2/models/ConsistencyRequest.java | 91 +++++++++++++++++-- .../v2/stub/AwaitConsistencyCallable.java | 34 +++++-- .../stub/EnhancedBigtableTableAdminStub.java | 28 +++++- 3 files changed, 135 insertions(+), 18 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java index f338776503..ef6a3d762a 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyRequest.java @@ -43,9 +43,11 @@ public abstract class ConsistencyRequest { @Nullable public abstract String getConsistencyToken(); + protected abstract boolean isFullyQualified(); + public static ConsistencyRequest forReplication(String tableId) { return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null); + tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null, false); } /** @@ -59,20 +61,41 @@ public static ConsistencyRequest forReplication(String tableId, String consisten Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, consistencyToken); + tableId, + CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, + consistencyToken, + false); } public static ConsistencyRequest forDataBoost(String tableId) { return new AutoValue_ConsistencyRequest( - tableId, CheckConsistencyRequest.ModeCase.DATA_BOOST_READ_LOCAL_WRITES, null); + tableId, CheckConsistencyRequest.ModeCase.DATA_BOOST_READ_LOCAL_WRITES, null, false); } @InternalApi - public CheckConsistencyRequest toCheckConsistencyProto( - TableAdminRequestContext requestContext, String token) { + public static ConsistencyRequest forReplicationFromTableName(String tableName) { + Preconditions.checkArgument( + TableName.isParsableFrom(tableName), "tableName must be a fully qualified table name"); + return new AutoValue_ConsistencyRequest( + tableName, CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, null, true); + } + + @InternalApi + public static ConsistencyRequest forReplicationFromTableName( + String tableName, String consistencyToken) { + Preconditions.checkArgument( + TableName.isParsableFrom(tableName), "tableName must be a fully qualified table name"); + Preconditions.checkNotNull(consistencyToken, "consistencyToken must not be null"); + + return new AutoValue_ConsistencyRequest( + tableName, + CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES, + consistencyToken, + true); + } + + private CheckConsistencyRequest.Builder buildBaseRequest(String name, String token) { CheckConsistencyRequest.Builder builder = CheckConsistencyRequest.newBuilder(); - TableName tableName = - TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); if (getMode().equals(CheckConsistencyRequest.ModeCase.STANDARD_READ_REMOTE_WRITES)) { builder.setStandardReadRemoteWrites(StandardReadRemoteWrites.newBuilder().build()); @@ -80,16 +103,68 @@ public CheckConsistencyRequest toCheckConsistencyProto( builder.setDataBoostReadLocalWrites(DataBoostReadLocalWrites.newBuilder().build()); } - return builder.setName(tableName.toString()).setConsistencyToken(token).build(); + return builder.setName(name).setConsistencyToken(token); + } + + /** + * Creates a CheckConsistencyRequest proto. This variant is used when the ConsistencyRequest was + * initialized with a short table ID, relying on the TableAdminRequestContext to construct the + * fully qualified table name. + */ + @InternalApi + public CheckConsistencyRequest toCheckConsistencyProto( + TableAdminRequestContext requestContext, String token) { + Preconditions.checkState( + !isFullyQualified(), + "Use toCheckConsistencyProto(String token) for fully qualified table names."); + TableName tableName = + TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); + + return buildBaseRequest(tableName.toString(), token).build(); } + /** + * Creates a CheckConsistencyRequest proto. This variant is used when the ConsistencyRequest was + * initialized with a fully qualified table name, eliminating the need for a request context. + */ + @InternalApi + public CheckConsistencyRequest toCheckConsistencyProto(String token) { + Preconditions.checkState( + isFullyQualified(), + "Use toCheckConsistencyProto(TableAdminRequestContext, String) for non-qualified table" + + " names."); + + return buildBaseRequest(getTableId(), token).build(); + } + + /** + * Creates a GenerateConsistencyTokenRequest proto. This variant is used when the + * ConsistencyRequest was initialized with a short table ID, relying on the + * TableAdminRequestContext to construct the fully qualified table name. + */ @InternalApi public GenerateConsistencyTokenRequest toGenerateTokenProto( TableAdminRequestContext requestContext) { + Preconditions.checkState( + !isFullyQualified(), "Use toGenerateTokenProto() for fully qualified table names."); GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); TableName tableName = TableName.of(requestContext.getProjectId(), requestContext.getInstanceId(), getTableId()); return builder.setName(tableName.toString()).build(); } + + /** + * Creates a GenerateConsistencyTokenRequest proto. This variant is used when the + * ConsistencyRequest was initialized with a fully qualified table name, eliminating the need for + * a request context. + */ + @InternalApi + public GenerateConsistencyTokenRequest toGenerateTokenProto() { + Preconditions.checkState( + isFullyQualified(), + "Use toGenerateTokenProto(TableAdminRequestContext) for non-qualified table names."); + GenerateConsistencyTokenRequest.Builder builder = GenerateConsistencyTokenRequest.newBuilder(); + return builder.setName(getTableId()).build(); + } } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java index b4e42e2354..a8ccdd9704 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java @@ -42,6 +42,7 @@ import com.google.common.util.concurrent.MoreExecutors; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; +import javax.annotation.Nullable; /** * Callable that waits until either replication or Data Boost has caught up to the point it was @@ -56,7 +57,7 @@ class AwaitConsistencyCallable extends UnaryCallable { private final UnaryCallable checkCallable; private final RetryingExecutor executor; - private final TableAdminRequestContext requestContext; + @Nullable private final TableAdminRequestContext requestContext; static AwaitConsistencyCallable create( UnaryCallable @@ -64,7 +65,7 @@ static AwaitConsistencyCallable create( UnaryCallable checkCallable, ClientContext clientContext, RetrySettings pollingSettings, - TableAdminRequestContext requestContext) { + @Nullable TableAdminRequestContext requestContext) { RetryAlgorithm retryAlgorithm = new RetryAlgorithm<>( @@ -78,13 +79,22 @@ static AwaitConsistencyCallable create( generateCallable, checkCallable, retryingExecutor, requestContext); } + static AwaitConsistencyCallable create( + UnaryCallable + generateCallable, + UnaryCallable checkCallable, + ClientContext clientContext, + RetrySettings pollingSettings) { + return create(generateCallable, checkCallable, clientContext, pollingSettings, null); + } + @VisibleForTesting AwaitConsistencyCallable( UnaryCallable generateCallable, UnaryCallable checkCallable, RetryingExecutor executor, - TableAdminRequestContext requestContext) { + @Nullable TableAdminRequestContext requestContext) { this.generateCallable = generateCallable; this.checkCallable = checkCallable; this.executor = executor; @@ -98,13 +108,19 @@ public ApiFuture futureCall( // If the token is already provided, skip generation and poll directly. if (consistencyRequest.getConsistencyToken() != null) { CheckConsistencyRequest request = - consistencyRequest.toCheckConsistencyProto( - requestContext, consistencyRequest.getConsistencyToken()); + requestContext == null + ? consistencyRequest.toCheckConsistencyProto(consistencyRequest.getConsistencyToken()) + : consistencyRequest.toCheckConsistencyProto( + requestContext, consistencyRequest.getConsistencyToken()); return pollToken(request, apiCallContext); } ApiFuture tokenFuture = - generateToken(consistencyRequest.toGenerateTokenProto(requestContext), apiCallContext); + generateToken( + requestContext == null + ? consistencyRequest.toGenerateTokenProto() + : consistencyRequest.toGenerateTokenProto(requestContext), + apiCallContext); return ApiFutures.transformAsync( tokenFuture, @@ -112,8 +128,10 @@ public ApiFuture futureCall( @Override public ApiFuture apply(GenerateConsistencyTokenResponse input) { CheckConsistencyRequest request = - consistencyRequest.toCheckConsistencyProto( - requestContext, input.getConsistencyToken()); + requestContext == null + ? consistencyRequest.toCheckConsistencyProto(input.getConsistencyToken()) + : consistencyRequest.toCheckConsistencyProto( + requestContext, input.getConsistencyToken()); return pollToken(request, apiCallContext); } }, diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java index e68cafca54..3c5a585c0f 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/EnhancedBigtableTableAdminStub.java @@ -54,7 +54,7 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final BigtableTableAdminStubSettings settings; private final ClientContext clientContext; - private final TableAdminRequestContext requestContext; + @javax.annotation.Nullable private final TableAdminRequestContext requestContext; @Deprecated private final AwaitReplicationCallable awaitReplicationCallable; @@ -62,6 +62,30 @@ public class EnhancedBigtableTableAdminStub extends GrpcBigtableTableAdminStub { private final OperationCallable optimizeRestoredTableOperationBaseCallable; + /** + * Creates an instance of {@link EnhancedBigtableTableAdminStub} using the provided settings. This + * variant is used by the V2 client stack which relies on fully qualified table names and + * therefore does not require a {@link TableAdminRequestContext}. + * + * @param settings The settings used to configure the stub. + * @return A new instance of {@code EnhancedBigtableTableAdminStub}. + * @throws IOException If there are errors creating the underlying client context. + */ + public static EnhancedBigtableTableAdminStub createEnhanced( + BigtableTableAdminStubSettings settings) throws IOException { + return new EnhancedBigtableTableAdminStub(settings, ClientContext.create(settings), null); + } + + /** + * Creates an instance of {@link EnhancedBigtableTableAdminStub} using the provided settings. This + * variant is used by the legacy client stack which relies on short table IDs and requires a + * {@link TableAdminRequestContext} to construct fully qualified table names. + * + * @param settings The settings used to configure the stub. + * @param requestContext The context used to format short table IDs. + * @return A new instance of {@code EnhancedBigtableTableAdminStub}. + * @throws IOException If there are errors creating the underlying client context. + */ public static EnhancedBigtableTableAdminStub createEnhanced( BigtableTableAdminStubSettings settings, TableAdminRequestContext requestContext) throws IOException { @@ -72,7 +96,7 @@ public static EnhancedBigtableTableAdminStub createEnhanced( private EnhancedBigtableTableAdminStub( BigtableTableAdminStubSettings settings, ClientContext clientContext, - TableAdminRequestContext requestContext) + @javax.annotation.Nullable TableAdminRequestContext requestContext) throws IOException { super(settings, clientContext); From c6ff5c5ee67b49def096c27770818963cc1cd5c5 Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Thu, 23 Apr 2026 11:56:40 -0400 Subject: [PATCH 12/14] fix build --- .../bigtable/admin/v2/stub/AwaitConsistencyCallable.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java index a8ccdd9704..f772421b8d 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/stub/AwaitConsistencyCallable.java @@ -51,7 +51,7 @@ *

This callable wraps GenerateConsistencyToken and CheckConsistency RPCs. It will generate a * token then poll until isConsistent is true. */ -class AwaitConsistencyCallable extends UnaryCallable { +public class AwaitConsistencyCallable extends UnaryCallable { private final UnaryCallable generateCallable; private final UnaryCallable checkCallable; @@ -59,7 +59,7 @@ class AwaitConsistencyCallable extends UnaryCallable { @Nullable private final TableAdminRequestContext requestContext; - static AwaitConsistencyCallable create( + public static AwaitConsistencyCallable create( UnaryCallable generateCallable, UnaryCallable checkCallable, @@ -79,7 +79,7 @@ static AwaitConsistencyCallable create( generateCallable, checkCallable, retryingExecutor, requestContext); } - static AwaitConsistencyCallable create( + public static AwaitConsistencyCallable create( UnaryCallable generateCallable, UnaryCallable checkCallable, From 0341958021292c2667230b594e65ca50172b1016 Mon Sep 17 00:00:00 2001 From: Jin Seop Kim Date: Thu, 23 Apr 2026 12:10:42 -0400 Subject: [PATCH 13/14] PR feedback --- .../bigtable/admin/v2/BigtableInstanceAdminClientV2.java | 4 ++-- .../cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java | 4 ++-- .../bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java | 4 ++-- .../bigtable/admin/v2/BigtableTableAdminClientV2Test.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java index f8284a09c8..6d59cce762 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2.java @@ -37,13 +37,13 @@ protected BigtableInstanceAdminClientV2(BigtableInstanceAdminStub stub) { } /** Constructs an instance of BigtableInstanceAdminClientV2 with the given settings. */ - public static final BigtableInstanceAdminClientV2 createClient( + public static final BigtableInstanceAdminClientV2 create( BaseBigtableInstanceAdminSettings settings) throws IOException { return new BigtableInstanceAdminClientV2(settings); } /** Constructs an instance of BigtableInstanceAdminClientV2 with the given stub. */ - public static final BigtableInstanceAdminClientV2 createClient(BigtableInstanceAdminStub stub) { + public static final BigtableInstanceAdminClientV2 create(BigtableInstanceAdminStub stub) { return new BigtableInstanceAdminClientV2(stub); } } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java index f61f2f0904..682a38e7fe 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -194,13 +194,13 @@ public Empty apply(OperationSnapshot input) { } /** Constructs an instance of BigtableTableAdminClientV2 with the given settings. */ - public static final BigtableTableAdminClientV2 createClient( + public static final BigtableTableAdminClientV2 create( BaseBigtableTableAdminSettings settings) throws IOException { return new BigtableTableAdminClientV2(settings); } /** Constructs an instance of BigtableTableAdminClientV2 with the given stub. */ - public static final BigtableTableAdminClientV2 createClient(BigtableTableAdminStub stub) { + public static final BigtableTableAdminClientV2 create(BigtableTableAdminStub stub) { return new BigtableTableAdminClientV2(stub); } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java index 7abf4941a6..2e19776082 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientV2Test.java @@ -29,7 +29,7 @@ public class BigtableInstanceAdminClientV2Test { @Test public void testCreateWithStub() { BigtableInstanceAdminStub mockStub = Mockito.mock(BigtableInstanceAdminStub.class); - BigtableInstanceAdminClientV2 client = BigtableInstanceAdminClientV2.createClient(mockStub); + BigtableInstanceAdminClientV2 client = BigtableInstanceAdminClientV2.create(mockStub); assertThat(client).isNotNull(); } @@ -41,7 +41,7 @@ public void testCreateClientWithSettings() throws Exception { .setCredentialsProvider(com.google.api.gax.core.NoCredentialsProvider.create()) .build(); try (BigtableInstanceAdminClientV2 settingsClient = - BigtableInstanceAdminClientV2.createClient(settings)) { + BigtableInstanceAdminClientV2.create(settings)) { assertThat(settingsClient).isNotNull(); } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java index 104088d2b3..d86a3ddff0 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java @@ -147,7 +147,7 @@ public void testCreateClientWithSettings() throws Exception { .setCredentialsProvider(com.google.api.gax.core.NoCredentialsProvider.create()) .build(); try (BigtableTableAdminClientV2 settingsClient = - BigtableTableAdminClientV2.createClient(settings)) { + BigtableTableAdminClientV2.create(settings)) { // Verify that the underlying stub is NOT an Enhanced stub by default // but the client has successfully initialized its own callables. assertThat(settingsClient.getStub()).isNotInstanceOf(EnhancedBigtableTableAdminStub.class); From 2fcffb599079fd5f1477c202f0503921a9cecd1f Mon Sep 17 00:00:00 2001 From: cloud-java-bot Date: Thu, 23 Apr 2026 16:15:38 +0000 Subject: [PATCH 14/14] chore: generate libraries at Thu Apr 23 16:12:59 UTC 2026 --- .../cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java | 4 ++-- .../bigtable/admin/v2/BigtableTableAdminClientV2Test.java | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java index 682a38e7fe..d654ab0064 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2.java @@ -194,8 +194,8 @@ public Empty apply(OperationSnapshot input) { } /** Constructs an instance of BigtableTableAdminClientV2 with the given settings. */ - public static final BigtableTableAdminClientV2 create( - BaseBigtableTableAdminSettings settings) throws IOException { + public static final BigtableTableAdminClientV2 create(BaseBigtableTableAdminSettings settings) + throws IOException { return new BigtableTableAdminClientV2(settings); } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java index d86a3ddff0..be6cd19be6 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientV2Test.java @@ -146,8 +146,7 @@ public void testCreateClientWithSettings() throws Exception { BaseBigtableTableAdminSettings.newBuilder() .setCredentialsProvider(com.google.api.gax.core.NoCredentialsProvider.create()) .build(); - try (BigtableTableAdminClientV2 settingsClient = - BigtableTableAdminClientV2.create(settings)) { + try (BigtableTableAdminClientV2 settingsClient = BigtableTableAdminClientV2.create(settings)) { // Verify that the underlying stub is NOT an Enhanced stub by default // but the client has successfully initialized its own callables. assertThat(settingsClient.getStub()).isNotInstanceOf(EnhancedBigtableTableAdminStub.class);