|
15 | 15 | */ |
16 | 16 | package com.google.cloud.bigtable.admin.v2; |
17 | 17 |
|
| 18 | +import com.google.api.core.ApiFunction; |
18 | 19 | import com.google.api.core.ApiFuture; |
19 | 20 | import com.google.api.core.ApiFutures; |
| 21 | +import com.google.api.gax.grpc.GrpcCallSettings; |
| 22 | +import com.google.api.gax.grpc.GrpcCallableFactory; |
| 23 | +import com.google.api.gax.grpc.ProtoOperationTransformers.MetadataTransformer; |
| 24 | +import com.google.api.gax.grpc.ProtoOperationTransformers.ResponseTransformer; |
| 25 | +import com.google.api.gax.longrunning.OperationSnapshot; |
| 26 | +import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; |
| 27 | +import com.google.api.gax.retrying.RetrySettings; |
20 | 28 | import com.google.api.gax.rpc.ApiExceptions; |
| 29 | +import com.google.api.gax.rpc.ClientContext; |
| 30 | +import com.google.api.gax.rpc.OperationCallSettings; |
| 31 | +import com.google.api.gax.rpc.OperationCallable; |
| 32 | +import com.google.api.gax.rpc.UnaryCallSettings; |
| 33 | +import com.google.api.gax.rpc.UnaryCallable; |
| 34 | +import com.google.bigtable.admin.v2.OptimizeRestoredTableMetadata; |
21 | 35 | import com.google.cloud.bigtable.admin.v2.models.ConsistencyRequest; |
22 | 36 | import com.google.cloud.bigtable.admin.v2.models.OptimizeRestoredTableOperationToken; |
23 | 37 | import com.google.cloud.bigtable.admin.v2.models.RestoredTableResult; |
| 38 | +import com.google.cloud.bigtable.admin.v2.stub.AwaitConsistencyCallable; |
24 | 39 | import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStub; |
25 | | -import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; |
| 40 | +import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; |
26 | 41 | import com.google.common.base.Strings; |
| 42 | +import com.google.common.util.concurrent.MoreExecutors; |
| 43 | +import com.google.longrunning.Operation; |
27 | 44 | import com.google.protobuf.Empty; |
| 45 | +import io.grpc.MethodDescriptor; |
| 46 | +import io.grpc.MethodDescriptor.Marshaller; |
| 47 | +import io.grpc.MethodDescriptor.MethodType; |
28 | 48 | import java.io.IOException; |
| 49 | +import java.io.InputStream; |
29 | 50 | import java.util.concurrent.ExecutionException; |
| 51 | +import org.threeten.bp.Duration; |
30 | 52 |
|
31 | 53 | /** |
32 | 54 | * Modern Cloud Bigtable Table Admin Client. |
|
36 | 58 | * generator cannot handle natively (e.g., chained Long Running Operations, Consistency Polling). |
37 | 59 | */ |
38 | 60 | public class BigtableTableAdminClientV2 extends BaseBigtableTableAdminClient { |
| 61 | + private final AwaitConsistencyCallable awaitConsistencyCallable; |
| 62 | + private final OperationCallable<Void, Empty, OptimizeRestoredTableMetadata> |
| 63 | + optimizeRestoredTableOperationBaseCallable; |
39 | 64 |
|
40 | 65 | protected BigtableTableAdminClientV2(BaseBigtableTableAdminSettings settings) throws IOException { |
41 | 66 | super(settings); |
| 67 | + this.awaitConsistencyCallable = |
| 68 | + createAwaitConsistencyCallable((BigtableTableAdminStubSettings) settings.getStubSettings()); |
| 69 | + this.optimizeRestoredTableOperationBaseCallable = |
| 70 | + createOptimizeRestoredTableOperationBaseCallable( |
| 71 | + (BigtableTableAdminStubSettings) settings.getStubSettings()); |
42 | 72 | } |
43 | 73 |
|
44 | 74 | protected BigtableTableAdminClientV2(BigtableTableAdminStub stub) { |
45 | 75 | super(stub); |
| 76 | + this.awaitConsistencyCallable = null; |
| 77 | + this.optimizeRestoredTableOperationBaseCallable = null; |
| 78 | + } |
| 79 | + |
| 80 | + private AwaitConsistencyCallable createAwaitConsistencyCallable( |
| 81 | + BigtableTableAdminStubSettings settings) throws IOException { |
| 82 | + ClientContext clientContext = ClientContext.create(settings); |
| 83 | + // TODO(igorbernstein2): expose polling settings |
| 84 | + RetrySettings pollingSettings = |
| 85 | + RetrySettings.newBuilder() |
| 86 | + .setTotalTimeout( |
| 87 | + settings.checkConsistencySettings().getRetrySettings().getTotalTimeout()) |
| 88 | + .setInitialRetryDelay(Duration.ofSeconds(10)) |
| 89 | + .setRetryDelayMultiplier(1.0) |
| 90 | + .setMaxRetryDelay(Duration.ofSeconds(10)) |
| 91 | + .setInitialRpcTimeout(Duration.ZERO) |
| 92 | + .setMaxRpcTimeout(Duration.ZERO) |
| 93 | + .setRpcTimeoutMultiplier(1.0) |
| 94 | + .build(); |
| 95 | + |
| 96 | + return AwaitConsistencyCallable.create( |
| 97 | + getStub().generateConsistencyTokenCallable(), |
| 98 | + getStub().checkConsistencyCallable(), |
| 99 | + clientContext, |
| 100 | + pollingSettings); |
| 101 | + } |
| 102 | + |
| 103 | + private OperationCallable<Void, Empty, OptimizeRestoredTableMetadata> |
| 104 | + createOptimizeRestoredTableOperationBaseCallable(BigtableTableAdminStubSettings settings) |
| 105 | + throws IOException { |
| 106 | + ClientContext clientContext = ClientContext.create(settings); |
| 107 | + |
| 108 | + GrpcCallSettings<Void, Operation> unusedInitialCallSettings = |
| 109 | + GrpcCallSettings.create( |
| 110 | + MethodDescriptor.<Void, Operation>newBuilder() |
| 111 | + .setType(MethodType.UNARY) |
| 112 | + .setFullMethodName( |
| 113 | + "google.bigtable.admin.v2.BigtableTableAdmin/OptimizeRestoredTable") |
| 114 | + .setRequestMarshaller( |
| 115 | + new Marshaller<Void>() { |
| 116 | + @Override |
| 117 | + public InputStream stream(Void value) { |
| 118 | + throw new UnsupportedOperationException("not used"); |
| 119 | + } |
| 120 | + |
| 121 | + @Override |
| 122 | + public Void parse(InputStream stream) { |
| 123 | + throw new UnsupportedOperationException("not used"); |
| 124 | + } |
| 125 | + }) |
| 126 | + .setResponseMarshaller( |
| 127 | + new Marshaller<Operation>() { |
| 128 | + @Override |
| 129 | + public InputStream stream(Operation value) { |
| 130 | + throw new UnsupportedOperationException("not used"); |
| 131 | + } |
| 132 | + |
| 133 | + @Override |
| 134 | + public Operation parse(InputStream stream) { |
| 135 | + throw new UnsupportedOperationException("not used"); |
| 136 | + } |
| 137 | + }) |
| 138 | + .build()); |
| 139 | + |
| 140 | + final MetadataTransformer<OptimizeRestoredTableMetadata> protoMetadataTransformer = |
| 141 | + MetadataTransformer.create(OptimizeRestoredTableMetadata.class); |
| 142 | + |
| 143 | + final ResponseTransformer<com.google.protobuf.Empty> protoResponseTransformer = |
| 144 | + ResponseTransformer.create(com.google.protobuf.Empty.class); |
| 145 | + |
| 146 | + OperationCallSettings<Void, Empty, OptimizeRestoredTableMetadata> operationCallSettings = |
| 147 | + OperationCallSettings.<Void, Empty, OptimizeRestoredTableMetadata>newBuilder() |
| 148 | + .setInitialCallSettings( |
| 149 | + UnaryCallSettings.<Void, OperationSnapshot>newUnaryCallSettingsBuilder() |
| 150 | + .setSimpleTimeoutNoRetries(Duration.ZERO) |
| 151 | + .build()) |
| 152 | + .setMetadataTransformer( |
| 153 | + new ApiFunction<OperationSnapshot, OptimizeRestoredTableMetadata>() { |
| 154 | + @Override |
| 155 | + public OptimizeRestoredTableMetadata apply(OperationSnapshot input) { |
| 156 | + return protoMetadataTransformer.apply(input); |
| 157 | + } |
| 158 | + }) |
| 159 | + .setResponseTransformer( |
| 160 | + new ApiFunction<OperationSnapshot, Empty>() { |
| 161 | + @Override |
| 162 | + public Empty apply(OperationSnapshot input) { |
| 163 | + return protoResponseTransformer.apply(input); |
| 164 | + } |
| 165 | + }) |
| 166 | + .setPollingAlgorithm( |
| 167 | + OperationTimedPollAlgorithm.create( |
| 168 | + RetrySettings.newBuilder() |
| 169 | + .setInitialRetryDelay(Duration.ofMillis(500L)) |
| 170 | + .setRetryDelayMultiplier(1.5) |
| 171 | + .setMaxRetryDelay(Duration.ofMillis(5000L)) |
| 172 | + .setInitialRpcTimeout(Duration.ZERO) |
| 173 | + .setRpcTimeoutMultiplier(1.0) |
| 174 | + .setMaxRpcTimeout(Duration.ZERO) |
| 175 | + .setTotalTimeout(Duration.ofMillis(600000L)) |
| 176 | + .build())) |
| 177 | + .build(); |
| 178 | + |
| 179 | + return GrpcCallableFactory.createOperationCallable( |
| 180 | + unusedInitialCallSettings, |
| 181 | + operationCallSettings, |
| 182 | + clientContext, |
| 183 | + getStub().getOperationsStub()); |
46 | 184 | } |
47 | 185 |
|
48 | 186 | /** Constructs an instance of BigtableTableAdminClientV2 with the given settings. */ |
49 | 187 | public static final BigtableTableAdminClientV2 createClient( |
50 | 188 | BaseBigtableTableAdminSettings settings) throws IOException { |
51 | | - // Explicitly create the enhanced stub |
52 | | - EnhancedBigtableTableAdminStub stub = |
53 | | - EnhancedBigtableTableAdminStub.createEnhanced( |
54 | | - (com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings) |
55 | | - settings.getStubSettings()); |
56 | | - // Pass the enhanced stub to the existing stub-based constructor |
57 | | - return new BigtableTableAdminClientV2(stub); |
| 189 | + return new BigtableTableAdminClientV2(settings); |
58 | 190 | } |
59 | 191 |
|
60 | 192 | /** Constructs an instance of BigtableTableAdminClientV2 with the given stub. */ |
@@ -90,9 +222,7 @@ public ApiFuture<Empty> awaitOptimizeRestoredTable(ApiFuture<RestoredTableResult |
90 | 222 | } |
91 | 223 |
|
92 | 224 | // 3. Return the future for the optimization operation |
93 | | - return ((EnhancedBigtableTableAdminStub) getStub()) |
94 | | - .awaitOptimizeRestoredTableCallable() |
95 | | - .resumeFutureCall(token.getOperationName()); |
| 225 | + return getOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName()); |
96 | 226 | } |
97 | 227 |
|
98 | 228 | /** |
@@ -140,9 +270,7 @@ public void awaitOptimizeRestoredTable(OptimizeRestoredTableOperationToken token |
140 | 270 | public ApiFuture<Void> awaitOptimizeRestoredTableAsync( |
141 | 271 | OptimizeRestoredTableOperationToken token) { |
142 | 272 | ApiFuture<Empty> emptyFuture = |
143 | | - ((EnhancedBigtableTableAdminStub) getStub()) |
144 | | - .awaitOptimizeRestoredTableCallable() |
145 | | - .resumeFutureCall(token.getOperationName()); |
| 273 | + getOptimizeRestoredTableCallable().resumeFutureCall(token.getOperationName()); |
146 | 274 | return ApiFutures.transform( |
147 | 275 | emptyFuture, |
148 | 276 | new com.google.api.core.ApiFunction<Empty, Void>() { |
@@ -175,8 +303,32 @@ public void waitForConsistency(String tableName, String consistencyToken) { |
175 | 303 | * @param consistencyToken The token to poll. |
176 | 304 | */ |
177 | 305 | public ApiFuture<Void> waitForConsistencyAsync(String tableName, String consistencyToken) { |
178 | | - return ((EnhancedBigtableTableAdminStub) getStub()) |
179 | | - .awaitConsistencyCallable() |
| 306 | + return getAwaitConsistencyCallable() |
180 | 307 | .futureCall(ConsistencyRequest.forReplicationFromTableName(tableName, consistencyToken)); |
181 | 308 | } |
| 309 | + |
| 310 | + private UnaryCallable<ConsistencyRequest, Void> getAwaitConsistencyCallable() { |
| 311 | + if (awaitConsistencyCallable != null) { |
| 312 | + return awaitConsistencyCallable; |
| 313 | + } |
| 314 | + // Fallback for tests or stub-based initialization |
| 315 | + if (getStub() instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { |
| 316 | + return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) |
| 317 | + .awaitConsistencyCallable(); |
| 318 | + } |
| 319 | + throw new IllegalStateException("AwaitConsistencyCallable not initialized."); |
| 320 | + } |
| 321 | + |
| 322 | + private OperationCallable<Void, Empty, OptimizeRestoredTableMetadata> |
| 323 | + getOptimizeRestoredTableCallable() { |
| 324 | + if (optimizeRestoredTableOperationBaseCallable != null) { |
| 325 | + return optimizeRestoredTableOperationBaseCallable; |
| 326 | + } |
| 327 | + // Fallback for tests or stub-based initialization |
| 328 | + if (getStub() instanceof com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) { |
| 329 | + return ((com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub) getStub()) |
| 330 | + .awaitOptimizeRestoredTableCallable(); |
| 331 | + } |
| 332 | + throw new IllegalStateException("OptimizeRestoredTableCallable not initialized."); |
| 333 | + } |
182 | 334 | } |
0 commit comments