From dcd7026a2b6b750736058ac187e9ad2e7bf3cf60 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 11 Oct 2018 10:47:13 -0400 Subject: [PATCH 1/6] Use gax's async error handling now that it has been upstreamed --- .../admin/v2/BigtableInstanceAdminClient.java | 66 ++++++------------- .../admin/v2/BigtableTableAdminClient.java | 47 ++++--------- 2 files changed, 32 insertions(+), 81 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java index 3cb16b00ef9d..2392d09bf542 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java @@ -19,6 +19,7 @@ import com.google.api.core.ApiFunction; import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; +import com.google.api.gax.rpc.ApiExceptions; import com.google.api.resourcenames.ResourceName; import com.google.bigtable.admin.v2.AppProfileName; import com.google.bigtable.admin.v2.ClusterName; @@ -46,9 +47,7 @@ import com.google.common.base.Verify; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; -import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.SetIamPolicyRequest; import com.google.iam.v1.TestIamPermissionsRequest; @@ -160,7 +159,7 @@ public void close() { */ @SuppressWarnings("WeakerAccess") public Instance createInstance(CreateInstanceRequest request) { - return awaitFuture(createInstanceAsync(request)); + return ApiExceptions.callAndTranslateApiException(createInstanceAsync(request)); } /** @@ -208,7 +207,7 @@ public Instance apply(com.google.bigtable.admin.v2.Instance proto) { */ @SuppressWarnings("WeakerAccess") public Instance updateInstance(UpdateInstanceRequest request) { - return awaitFuture(updateInstanceAsync(request)); + return ApiExceptions.callAndTranslateApiException(updateInstanceAsync(request)); } /** @@ -251,7 +250,7 @@ public Instance apply(com.google.bigtable.admin.v2.Instance proto) { */ @SuppressWarnings("WeakerAccess") public Instance getInstance(String id) { - return awaitFuture(getInstanceAsync(id)); + return ApiExceptions.callAndTranslateApiException(getInstanceAsync(id)); } /** @@ -302,7 +301,7 @@ public Instance apply(com.google.bigtable.admin.v2.Instance proto) { */ @SuppressWarnings("WeakerAccess") public List listInstances() { - return awaitFuture(listInstancesAsync()); + return ApiExceptions.callAndTranslateApiException(listInstancesAsync()); } /** @@ -385,7 +384,7 @@ public List apply(com.google.bigtable.admin.v2.ListInstancesResponse p */ @SuppressWarnings("WeakerAccess") public void deleteInstance(String instanceId) { - awaitFuture(deleteInstanceAsync(instanceId)); + ApiExceptions.callAndTranslateApiException(deleteInstanceAsync(instanceId)); } /** @@ -434,7 +433,7 @@ public Void apply(Empty input) { */ @SuppressWarnings("WeakerAccess") public Cluster createCluster(CreateClusterRequest request) { - return awaitFuture(createClusterAsync(request)); + return ApiExceptions.callAndTranslateApiException(createClusterAsync(request)); } /** @@ -478,7 +477,7 @@ public Cluster apply(com.google.bigtable.admin.v2.Cluster proto) { */ @SuppressWarnings("WeakerAccess") public Cluster getCluster(String instanceId, String clusterId) { - return awaitFuture(getClusterAsync(instanceId, clusterId)); + return ApiExceptions.callAndTranslateApiException(getClusterAsync(instanceId, clusterId)); } /** @@ -531,7 +530,7 @@ public Cluster apply(com.google.bigtable.admin.v2.Cluster proto) { */ @SuppressWarnings("WeakerAccess") public List listClusters(String instanceId) { - return awaitFuture(listClustersAsync(instanceId)); + return ApiExceptions.callAndTranslateApiException(listClustersAsync(instanceId)); } /** @@ -615,7 +614,8 @@ public List apply(com.google.bigtable.admin.v2.ListClustersResponse pro */ @SuppressWarnings("WeakerAccess") public Cluster resizeCluster(String instanceId, String clusterId, int numServeNodes) { - return awaitFuture(resizeClusterAsync(instanceId, clusterId, numServeNodes)); + return ApiExceptions.callAndTranslateApiException( + resizeClusterAsync(instanceId, clusterId, numServeNodes)); } /** @@ -662,7 +662,7 @@ public Cluster apply(com.google.bigtable.admin.v2.Cluster proto) { */ @SuppressWarnings("WeakerAccess") public void deleteCluster(String instanceId, String clusterId) { - awaitFuture(deleteClusterAsync(instanceId, clusterId)); + ApiExceptions.callAndTranslateApiException(deleteClusterAsync(instanceId, clusterId)); } /** @@ -713,7 +713,7 @@ public Void apply(Empty input) { */ @SuppressWarnings("WeakerAccess") public AppProfile createAppProfile(CreateAppProfileRequest request) { - return awaitFuture(createAppProfileAsync(request)); + return ApiExceptions.callAndTranslateApiException(createAppProfileAsync(request)); } /** @@ -759,7 +759,7 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { */ @SuppressWarnings("WeakerAccess") public AppProfile getAppProfile(String instanceId, String appProfileId) { - return awaitFuture(getAppProfileAsync(instanceId, appProfileId)); + return ApiExceptions.callAndTranslateApiException(getAppProfileAsync(instanceId, appProfileId)); } /** @@ -808,7 +808,7 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { */ @SuppressWarnings("WeakerAccess") public List listAppProfiles(String instanceId) { - return awaitFuture(listAppProfilesAsync(instanceId)); + return ApiExceptions.callAndTranslateApiException(listAppProfilesAsync(instanceId)); } /** @@ -911,7 +911,7 @@ public List apply(List inpu */ @SuppressWarnings("WeakerAccess") public AppProfile updateAppProfile(UpdateAppProfileRequest request) { - return awaitFuture(updateAppProfileAsync(request)); + return ApiExceptions.callAndTranslateApiException(updateAppProfileAsync(request)); } /** @@ -966,7 +966,7 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { */ @SuppressWarnings("WeakerAccess") public void deleteAppProfile(String instanceId, String appProfileId) { - awaitFuture(deleteAppProfileAsync(instanceId, appProfileId)); + ApiExceptions.callAndTranslateApiException(deleteAppProfileAsync(instanceId, appProfileId)); } /** @@ -1016,7 +1016,7 @@ public Void apply(Empty input) { */ @SuppressWarnings("WeakerAccess") public Policy getIamPolicy(String instanceId) { - return awaitFuture(getIamPolicyAsync(instanceId)); + return ApiExceptions.callAndTranslateApiException(getIamPolicyAsync(instanceId)); } /** @@ -1083,7 +1083,7 @@ public Policy apply(com.google.iam.v1.Policy proto) { */ @SuppressWarnings("WeakerAccess") public Policy setIamPolicy(String instanceId, Policy policy) { - return awaitFuture(setIamPolicyAsync(instanceId, policy)); + return ApiExceptions.callAndTranslateApiException(setIamPolicyAsync(instanceId, policy)); } /** @@ -1210,7 +1210,8 @@ public ApiFuture> testIamPermissionAsync(String instanceId, String. */ @SuppressWarnings("WeakerAccess") public List testIamPermission(ResourceName resourceName, String... permissions) { - return awaitFuture(testIamPermissionAsync(resourceName, permissions)); + return ApiExceptions.callAndTranslateApiException( + testIamPermissionAsync(resourceName, permissions)); } @@ -1276,29 +1277,4 @@ public com.google.iam.v1.Policy toPb(Policy policy) { return super.toPb(policy); } } - - /** - * Awaits the result of a future, taking care to propagate errors while maintaining the call site - * in a suppressed exception. This allows semantic errors to be caught across threads, while - * preserving the call site in the error. The caller's stacktrace will be made available as a - * suppressed exception. - */ - // TODO(igorbernstein2): try to move this into gax - private T awaitFuture(ApiFuture future) { - RuntimeException error; - try { - return Futures.getUnchecked(future); - } catch (UncheckedExecutionException e) { - if (e.getCause() instanceof RuntimeException) { - error = (RuntimeException) e.getCause(); - } else { - error = e; - } - } catch (RuntimeException e) { - error = e; - } - // Add the caller's stack as a suppressed exception - error.addSuppressed(new RuntimeException("Encountered error while awaiting future")); - throw error; - } } diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java index eba6a51c4f01..7522a731a108 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java @@ -19,6 +19,7 @@ import com.google.api.core.ApiFunction; import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; +import com.google.api.gax.rpc.ApiExceptions; import com.google.bigtable.admin.v2.DeleteTableRequest; import com.google.bigtable.admin.v2.DropRowRangeRequest; import com.google.bigtable.admin.v2.GetTableRequest; @@ -33,9 +34,7 @@ import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; -import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.protobuf.ByteString; import com.google.protobuf.Empty; import java.io.IOException; @@ -149,7 +148,7 @@ public void close() { */ @SuppressWarnings("WeakerAccess") public Table createTable(CreateTableRequest request) { - return awaitFuture(createTableAsync(request)); + return ApiExceptions.callAndTranslateApiException(createTableAsync(request)); } /** @@ -222,7 +221,7 @@ public ApiFuture createTableAsync(CreateTableRequest request) { */ @SuppressWarnings("WeakerAccess") public Table modifyFamilies(ModifyColumnFamiliesRequest request) { - return awaitFuture(modifyFamiliesAsync(request)); + return ApiExceptions.callAndTranslateApiException(modifyFamiliesAsync(request)); } /** @@ -289,7 +288,7 @@ public ApiFuture
modifyFamiliesAsync(ModifyColumnFamiliesRequest request) */ @SuppressWarnings("WeakerAccess") public void deleteTable(String tableId) { - awaitFuture(deleteTableAsync(tableId)); + ApiExceptions.callAndTranslateApiException(deleteTableAsync(tableId)); } /** @@ -342,7 +341,7 @@ public ApiFuture deleteTableAsync(String tableId) { */ @SuppressWarnings("WeakerAccess") public Table getTable(String tableId) { - return awaitFuture(getTableAsync(tableId)); + return ApiExceptions.callAndTranslateApiException(getTableAsync(tableId)); } /** @@ -397,7 +396,7 @@ public ApiFuture
getTableAsync(String tableId) { // TODO(igorbernstein2): consider changing this method to use relative table ids. @SuppressWarnings("WeakerAccess") public List listTables() { - return awaitFuture(listTablesAsync()); + return ApiExceptions.callAndTranslateApiException(listTablesAsync()); } /** @@ -506,7 +505,7 @@ public List apply(List protos) { */ @SuppressWarnings("WeakerAccess") public void dropRowRange(String tableId, String rowKeyPrefix) { - awaitFuture(dropRowRangeAsync(tableId, rowKeyPrefix)); + ApiExceptions.callAndTranslateApiException(dropRowRangeAsync(tableId, rowKeyPrefix)); } /** @@ -552,7 +551,7 @@ public ApiFuture dropRowRangeAsync(String tableId, String rowKeyPrefix) { */ @SuppressWarnings("WeakerAccess") public void dropRowRange(String tableId, ByteString rowKeyPrefix) { - awaitFuture(dropRowRangeAsync(tableId, rowKeyPrefix)); + ApiExceptions.callAndTranslateApiException(dropRowRangeAsync(tableId, rowKeyPrefix)); } /** @@ -604,7 +603,7 @@ public ApiFuture dropRowRangeAsync(String tableId, ByteString rowKeyPrefix */ @SuppressWarnings("WeakerAccess") public void dropAllRows(String tableId) { - awaitFuture(dropAllRowsAsync(tableId)); + ApiExceptions.callAndTranslateApiException(dropAllRowsAsync(tableId)); } /** @@ -659,7 +658,8 @@ public ApiFuture dropAllRowsAsync(String tableId) { public void awaitReplication(String tableId) { TableName tableName = TableName .of(instanceName.getProject(), instanceName.getInstance(), tableId); - awaitFuture(stub.awaitReplicationCallable().futureCall(tableName)); + ApiExceptions + .callAndTranslateApiException(stub.awaitReplicationCallable().futureCall(tableName)); } /** @@ -734,29 +734,4 @@ public Void apply(Empty empty) { }, MoreExecutors.directExecutor()); } - - /** - * Awaits the result of a future, taking care to propagate errors while maintaining the call site - * in a suppressed exception. This allows semantic errors to be caught across threads, while - * preserving the call site in the error. The caller's stacktrace will be made available as a - * suppressed exception. - */ - // TODO(igorbernstein2): try to move this into gax - private T awaitFuture(ApiFuture future) { - RuntimeException error; - try { - return Futures.getUnchecked(future); - } catch (UncheckedExecutionException e) { - if (e.getCause() instanceof RuntimeException) { - error = (RuntimeException) e.getCause(); - } else { - error = e; - } - } catch (RuntimeException e) { - error = e; - } - // Add the caller's stack as a suppressed exception - error.addSuppressed(new RuntimeException("Encountered error while awaiting future")); - throw error; - } } From caf26216ea61b20605e4e2f2b0012100320c3dc5 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 11 Oct 2018 11:25:27 -0400 Subject: [PATCH 2/6] Bigtable: non-functional improvements * Add error handling examples to the javadocs * Use gax for error handling now that the code has been upstreamed * Fix outdated bigtable-admin readme --- .../google-cloud-bigtable-admin/README.md | 22 +-- .../bigtable/data/v2/BigtableDataClient.java | 160 ++++++++++++++++-- 2 files changed, 157 insertions(+), 25 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/README.md b/google-cloud-clients/google-cloud-bigtable-admin/README.md index 903031309bfe..a04f5683da36 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/README.md +++ b/google-cloud-clients/google-cloud-bigtable-admin/README.md @@ -72,25 +72,27 @@ at the top of your file: ```java -import com.google.bigtable.admin.v2.ColumnFamily; +import static com.google.cloud.bigtable.admin.v2.models.GCRules.GCRULES; import com.google.bigtable.admin.v2.InstanceName; import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.admin.v2.models.Table; ``` Then, to create a table, use the following code: ```java InstanceName instanceName = InstanceName.of("my-project", "my-instance"); -TableAdminClient tableAdminClient = TableAdminClient.create(instanceName); +BigtableTableAdminClient tableAdminClient = BigtableTableAdminClient.create(instanceName); -try { - CreateTable createTableReq = TableAdminRequests.createTable("tableId") - .addFamily("cf2", GCRULES.maxVersions(10)); - client.createTable(createTableReq); - -} finally { - tableAdminClient.close(); -} + try { + Table createdTable = tableAdminClient.createTable( + CreateTableRequest.of("my-table") + .addFamily("cf2", GCRULES.maxVersions(10) + ); + } finally { + tableAdminClient.close(); + } ``` ## Troubleshooting diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java index 4a7a48d33575..a333225af8b8 100644 --- a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java @@ -68,6 +68,14 @@ * service. * * + *

All RPC related errors are represented as subclasses of {@link com.google.api.gax.rpc.ApiException}. + * For example, a nonexistent table will trigger a {@link com.google.api.gax.rpc.NotFoundException}. + * Async methods will wrap the error inside the future. Synchronous methods will re-throw the async + * error but will try to preserve the caller's stacktrace by attaching a suppressed exception at the + * callsite. This allows callers to use typesafe exceptions, without losing their callsite. + * Streaming methods (ie. readRows) will re-throw the async exception (like sync methods) when + * starting iteration. + * *

See the individual methods for example code. * *

This class can be customized by passing in a custom instance of BigtableDataSettings to @@ -139,7 +147,20 @@ public static BigtableDataClient create(BigtableDataSettings settings) throws IO * try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) { * String tableId = "[TABLE]"; * - * ApiFuture result = bigtableClient.readRow(tableId, "key"); + * ApiFuture futureResult = bigtableClient.readRow(tableId, "key"); + * + * ApiFutures.addCallback(futureResult, new ApiFutureCallback() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to read a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(Row result) { + * System.out.println("Got row: " + result); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -159,6 +180,19 @@ public ApiFuture readRowAsync(String tableId, String rowKey) { * String tableId = "[TABLE]"; * * ApiFuture result = bigtableClient.readRow(tableId, ByteString.copyFromUtf8("key")); + * + * ApiFutures.addCallback(futureResult, new ApiFutureCallback() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to read a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(Row row) { + * System.out.println("Got row: " + row); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -184,8 +218,14 @@ public ApiFuture readRowAsync(String tableId, ByteString rowKey) { * .filter(FILTERS.qualifier().regex("[COLUMN PREFIX].*")); * * // Iterator style - * for(Row row : bigtableClient.readRows(query)) { - * // Do something with row + * try { + * for(Row row : bigtableClient.readRows(query)) { + * // Do something with row + * } + * } catch (NotFoundException e) { + * System.out.println("Tried to read a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); * } * } * } @@ -214,11 +254,15 @@ public ServerStream readRows(Query query) { * * client.readRowsAsync(query, new ResponseObserver() { * public void onStart(StreamController controller) { } - * public void onResponse(Row response) { + * public void onResponse(Row row) { * // Do something with Row * } * public void onError(Throwable t) { - * // Handle error before the stream completes + * if (t instanceof NotFoundException) { + * System.out.println("Tried to read a non-existent table"); + * } else { + * t.printStackTrace(); + * } * } * public void onComplete() { * // Handle stream completion @@ -247,13 +291,41 @@ public void readRowsAsync(Query query, ResponseObserver observer) { * .filter(FILTERS.qualifier().regex("[COLUMN PREFIX].*")); * * // Iterator style - * for(Row row : bigtableClient.readRowsCallable().call(query)) { - * // Do something with row - * } + * try { + * for(Row row : bigtableClient.readRowsCallable().call(query)) { + * // Do something with row + * } + * } catch (NotFoundException e) { + * System.out.println("Tried to read a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); + * }} + * + * // Sync style + * try { + * List rows = bigtableClient.readRowsCallable().all().call(query); + * } catch (NotFoundException e) { + * System.out.println("Tried to read a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); + * }} * * // Point look up * ApiFuture rowFuture = bigtableClient.readRowsCallable().first().futureCall(query); * + * ApiFutures.addCallback(rowFuture, new ApiFutureCallback() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to read a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(Row result) { + * System.out.println("Got row: " + result); + * } + * }, MoreExecutors.directExecutor()); + * * // etc * } * } @@ -282,8 +354,14 @@ public ServerStreamingCallable readRowsCallable() { * .filter(FILTERS.qualifier().regex("[COLUMN PREFIX].*")); * * // Iterator style - * for(CustomRow row : bigtableClient.readRowsCallable(new CustomRowAdapter()).call(query)) { - * // Do something with row + * try { + * for(CustomRow row : bigtableClient.readRowsCallable(new CustomRowAdapter()).call(query)) { + * // Do something with row + * } + * } catch (NotFoundException e) { + * System.out.println("Tried to read a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); * } * } * } @@ -306,7 +384,20 @@ public ServerStreamingCallable readRowsCallable(RowAdapter{@code * InstanceName instanceName = InstanceName.of("[PROJECT]", "[INSTANCE]"); * try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) { - * ApiFuture> keyOffsets = bigtableClient.sampleRowKeysAsync("[TABLE]"); + * ApiFuture> keyOffsetsFuture = bigtableClient.sampleRowKeysAsync("[TABLE]"); + * + * ApiFutures.addCallback(keyOffsetsFuture, new ApiFutureCallback>() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to sample keys of a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(List keyOffsets) { + * System.out.println("Got key offsets: " + keyOffsets); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -326,10 +417,29 @@ public ApiFuture> sampleRowKeysAsync(String tableId) { * InstanceName instanceName = InstanceName.of("[PROJECT]", "[INSTANCE]"); * try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) { * // Synchronous invocation - * List keyOffsets = bigtableClient.sampleRowKeysCallable().call("[TABLE]"); + * try { + * List keyOffsets = bigtableClient.sampleRowKeysCallable().call("[TABLE]"); + * } catch (NotFoundException e) { + * System.out.println("Tried to sample keys of a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); + * } * * // Asynchronous invocation - * ApiFuture> keyOffsets = bigtableClient.sampleRowKeysCallable().futureCall("[TABLE]"); + * ApiFuture> keyOffsetsFuture = bigtableClient.sampleRowKeysCallable().futureCall("[TABLE]"); + * + * ApiFutures.addCallback(keyOffsetsFuture, new ApiFutureCallback>() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to sample keys of a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(List keyOffsets) { + * System.out.println("Got key offsets: " + keyOffsets); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -349,7 +459,20 @@ public UnaryCallable> sampleRowKeysCallable() { * RowMutation mutation = RowMutation.create("[TABLE]", "[ROW KEY]") * .setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]"); * - * ApitFuture future = bigtableClient.mutateRowAsync(mutation); + * ApiFuture future = bigtableClient.mutateRowAsync(mutation); + * + * ApiFutures.addCallback(future, new ApiFutureCallback() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to mutate a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(Void ignored) { + * System.out.println("Successfully applied mutation"); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -369,7 +492,14 @@ public ApiFuture mutateRowAsync(RowMutation rowMutation) { * RowMutation mutation = RowMutation.create("[TABLE]", "[ROW KEY]") * .setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]"); * - * bigtableClient.mutateRowCallable().call(mutation); + * // Sync style + * try { + * bigtableClient.mutateRowCallable().call(mutation); + * } catch (NotFoundException e) { + * System.out.println("Tried to mutate a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); + * } * } * } */ From 791053cf63c9dd9441cfd9d6c20ce6dcdc2f169c Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 11 Oct 2018 11:28:05 -0400 Subject: [PATCH 3/6] spacing --- .../google-cloud-bigtable-admin/README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/README.md b/google-cloud-clients/google-cloud-bigtable-admin/README.md index a04f5683da36..aa64615504d0 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/README.md +++ b/google-cloud-clients/google-cloud-bigtable-admin/README.md @@ -85,14 +85,13 @@ InstanceName instanceName = InstanceName.of("my-project", "my-instance"); BigtableTableAdminClient tableAdminClient = BigtableTableAdminClient.create(instanceName); - try { - Table createdTable = tableAdminClient.createTable( - CreateTableRequest.of("my-table") - .addFamily("cf2", GCRULES.maxVersions(10) - ); - } finally { - tableAdminClient.close(); - } +try { + Table createdTable = tableAdminClient.createTable( + CreateTableRequest.of("my-table") + .addFamily("cf2", GCRULES.maxVersions(10)); +} finally { + tableAdminClient.close(); +} ``` ## Troubleshooting From d56196e4a301686b3822faff8c31b5ddbd414fd2 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 11 Oct 2018 11:35:09 -0400 Subject: [PATCH 4/6] more docs --- .../bigtable/data/v2/BigtableDataClient.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java index a333225af8b8..ddd174307274 100644 --- a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java @@ -521,7 +521,7 @@ public UnaryCallable mutateRowCallable() { * RowMutation mutation = RowMutation.create("[TABLE]", "[ROW KEY]") * .setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]"); * - * batcher.add(mutation); + * ApiFuture entryFuture = batcher.add(mutation); * } * } catch (BulkMutationFailure failure) { * // Handle error @@ -547,9 +547,23 @@ public BulkMutationBatcher newBulkMutationBatcher() { * try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) { * BulkMutation batch = BulkMutation.create("[TABLE]"); * for (String someValue : someCollection) { - * batch.add("[ROW KEY]", Mutation.create().setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]"); + * ApiFuture entryFuture = batch.add("[ROW KEY]", + * Mutation.create().setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]")); * } - * ApiFuture result = bigtableClient.bulkMutateRowsAsync(batch); + * ApiFuture resultFuture = bigtableClient.bulkMutateRowsAsync(batch); + * + * ApiFutures.addCallback(future, new ApiFutureCallback() { + * public void onFailure(Throwable t) { + * if (t instanceof BulkMutationFailure) { + * System.out.println("Some entries failed to apply"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(Void ignored) { + * System.out.println("Successfully applied all mutation"); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -569,7 +583,8 @@ public ApiFuture bulkMutateRowsAsync(BulkMutation mutation) { * try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) { * BulkMutation batch = BulkMutation.create("[TABLE]"); * for (String someValue : someCollection) { - * batch.add("[ROW KEY]", Mutation.create().setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]"); + * ApiFuture entryFuture = batch.add("[ROW KEY]", + * Mutation.create().setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]"); * } * bigtableClient.bulkMutateRowsCallable().call(batch); * } From 9bf68d8f60e95ff919c8861e80f2f47e05f34320 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 11 Oct 2018 11:40:17 -0400 Subject: [PATCH 5/6] more docs --- .../bigtable/data/v2/BigtableDataClient.java | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java index ddd174307274..1849f82a8009 100644 --- a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java @@ -610,6 +610,19 @@ public UnaryCallable bulkMutationCallable() { * ); * * ApiFuture future = bigtableClient.checkAndMutateRowAsync(mutation); + * + * ApiFutures.addCallback(future, new ApiFutureCallback() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to mutate a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(Boolean wasApplied) { + * System.out.println("Row was modified: " + wasApplied); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -632,7 +645,14 @@ public ApiFuture checkAndMutateRowAsync(ConditionalRowMutation mutation * .setCell("[FAMILY]", "[QUALIFIER]", "[VALUE]") * ); * - * boolean success = bigtableClient.checkAndMutateRowCallable().call(mutation); + * // Sync style + * try { + * boolean success = bigtableClient.checkAndMutateRowCallable().call(mutation); + * } catch (NotFoundException e) { + * System.out.println("Tried to mutate a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); + * } * } * } */ @@ -655,7 +675,20 @@ public UnaryCallable checkAndMutateRowCallable( * .increment("[FAMILY]", "[QUALIFIER]", 1) * .append("[FAMILY2]", "[QUALIFIER2]", "suffix"); * - * ApiFuture success = bigtableClient.readModifyWriteRowAsync(mutation); + * ApiFuture rowFuture = bigtableClient.readModifyWriteRowAsync(mutation); + * + * ApiFutures.addCallback(rowFuture, new ApiFutureCallback() { + * public void onFailure(Throwable t) { + * if (t instanceof NotFoundException) { + * System.out.println("Tried to mutate a non-existent table"); + * } else { + * t.printStackTrace(); + * } + * } + * public void onSuccess(Row resultingRow) { + * System.out.println("Resulting row: " + resultingRow); + * } + * }, MoreExecutors.directExecutor()); * } * } */ @@ -678,7 +711,13 @@ public ApiFuture readModifyWriteRowAsync(ReadModifyWriteRow mutation) { * .increment("[FAMILY]", "[QUALIFIER]", 1) * .append("[FAMILY2]", "[QUALIFIER2]", "suffix"); * - * Row row = bigtableClient.readModifyWriteRowCallable().call(mutation); + * try { + * Row row = bigtableClient.readModifyWriteRowCallable().call(mutation); + * } catch (NotFoundException e) { + * System.out.println("Tried to mutate a non-existent table"); + * } catch (RuntimeException e) { + * e.printStackTrace(); + * } * } * } */ From a4100bd227c98d78fef9467fe5ef88f9447f3c53 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Fri, 12 Oct 2018 14:13:27 -0400 Subject: [PATCH 6/6] address feedback --- .../google/cloud/bigtable/data/v2/BigtableDataClient.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java index 1849f82a8009..f7b4d7c4e22c 100644 --- a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClient.java @@ -179,7 +179,7 @@ public ApiFuture readRowAsync(String tableId, String rowKey) { * try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) { * String tableId = "[TABLE]"; * - * ApiFuture result = bigtableClient.readRow(tableId, ByteString.copyFromUtf8("key")); + * ApiFuture futureResult = bigtableClient.readRow(tableId, ByteString.copyFromUtf8("key")); * * ApiFutures.addCallback(futureResult, new ApiFutureCallback() { * public void onFailure(Throwable t) { @@ -552,7 +552,7 @@ public BulkMutationBatcher newBulkMutationBatcher() { * } * ApiFuture resultFuture = bigtableClient.bulkMutateRowsAsync(batch); * - * ApiFutures.addCallback(future, new ApiFutureCallback() { + * ApiFutures.addCallback(resultFuture, new ApiFutureCallback() { * public void onFailure(Throwable t) { * if (t instanceof BulkMutationFailure) { * System.out.println("Some entries failed to apply"); @@ -648,6 +648,9 @@ public ApiFuture checkAndMutateRowAsync(ConditionalRowMutation mutation * // Sync style * try { * boolean success = bigtableClient.checkAndMutateRowCallable().call(mutation); + * if (!success) { + * System.out.println("Row did not match conditions"); + * } * } catch (NotFoundException e) { * System.out.println("Tried to mutate a non-existent table"); * } catch (RuntimeException e) {