diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 090264303f..91bb69e63c 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:5ee35ee919254a3d1e7d4f8abbf1b8c8869ade317ceb2e4df709af1b4b3e9ca1 + digest: sha256:bf5639d265d70f6137d57d42ae781a6f4e26d4085ff4e018e71350480f9b3996 diff --git a/.kokoro/requirements.in b/.kokoro/requirements.in index b19a8dbfdd..2092cc741d 100644 --- a/.kokoro/requirements.in +++ b/.kokoro/requirements.in @@ -1,5 +1,5 @@ gcp-docuploader -gcp-releasetool +gcp-releasetool>=1.10.5 # required for compatibility with cryptography>=39.x wheel setuptools typing-extensions diff --git a/.kokoro/requirements.txt b/.kokoro/requirements.txt index cfadd22ce9..c80f0a87cc 100644 --- a/.kokoro/requirements.txt +++ b/.kokoro/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.9 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile --allow-unsafe --generate-hashes requirements.in @@ -126,9 +126,9 @@ gcp-docuploader==0.6.4 \ --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \ --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf # via -r requirements.in -gcp-releasetool==1.9.1 \ - --hash=sha256:952f4055d5d986b070ae2a71c4410b250000f9cc5a1e26398fcd55a5bbc5a15f \ - --hash=sha256:d0d3c814a97c1a237517e837d8cfa668ced8df4b882452578ecef4a4e79c583b +gcp-releasetool==1.10.5 \ + --hash=sha256:174b7b102d704b254f2a26a3eda2c684fd3543320ec239baf771542a2e58e109 \ + --hash=sha256:e29d29927fe2ca493105a82958c6873bb2b90d503acac56be2c229e74de0eec9 # via -r requirements.in google-api-core==2.8.2 \ --hash=sha256:06f7244c640322b508b125903bb5701bebabce8832f85aba9335ec00b3d02edc \ @@ -374,6 +374,10 @@ secretstorage==3.3.3 \ --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 # via keyring +setuptools==67.3.2 \ + --hash=sha256:95f00380ef2ffa41d9bba85d95b27689d923c93dfbafed4aecd7cf988a25e012 \ + --hash=sha256:bb6d8e508de562768f2027902929f8523932fcd1fb784e6d573d2cafac995a48 + # via -r requirements.in six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 diff --git a/CHANGELOG.md b/CHANGELOG.md index 03bd1e243a..a3ed79caa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,54 @@ # Changelog +## [2.20.3](https://github.com/googleapis/java-bigtable/compare/v2.20.2...v2.20.3) (2023-04-03) + + +### Dependencies + +* Upgrade shared dependencies to 3.6.0 and monitoring to 3.15.0 ([#1688](https://github.com/googleapis/java-bigtable/issues/1688)) ([c0bad0d](https://github.com/googleapis/java-bigtable/commit/c0bad0d637179e0e8ed80e9716203ae8f11e5cb4)) + +## [2.20.2](https://github.com/googleapis/java-bigtable/compare/v2.20.1...v2.20.2) (2023-03-29) + + +### Bug Fixes + +* Higher application blocking latency precision ([#1676](https://github.com/googleapis/java-bigtable/issues/1676)) ([45ce93b](https://github.com/googleapis/java-bigtable/commit/45ce93bb52112391b9c3a90f10f51279839bea1b)) +* Make ChangeStreamRecord interface serializable ([#1685](https://github.com/googleapis/java-bigtable/issues/1685)) ([b97badb](https://github.com/googleapis/java-bigtable/commit/b97badbaa30588c578bfacc8183e77baaa656bd9)) +* Mark readRow requests as unary operations ([#1679](https://github.com/googleapis/java-bigtable/issues/1679)) ([f88bb67](https://github.com/googleapis/java-bigtable/commit/f88bb67a7a63450b8cd29f01660cf677ddfe436c)) + +## [2.20.1](https://github.com/googleapis/java-bigtable/compare/v2.20.0...v2.20.1) (2023-03-21) + + +### Bug Fixes + +* If new_partitions is size 0, do not enforce size check ([#1673](https://github.com/googleapis/java-bigtable/issues/1673)) ([07bcfd9](https://github.com/googleapis/java-bigtable/commit/07bcfd9a0967f781fb8e5e0d764654dbf7bcda91)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-monitoring-bom to v3.14.0 ([#1668](https://github.com/googleapis/java-bigtable/issues/1668)) ([06f9615](https://github.com/googleapis/java-bigtable/commit/06f96156705a2a7897a31d11dad864afe94de693)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.5.0 ([#1670](https://github.com/googleapis/java-bigtable/issues/1670)) ([74cebf3](https://github.com/googleapis/java-bigtable/commit/74cebf3a5ab58f3fd3ae95583ba2421b733deda8)) + +## [2.20.0](https://github.com/googleapis/java-bigtable/compare/v2.19.2...v2.20.0) (2023-03-02) + + +### Features + +* Add getNewPartitions method to CloseStream for Bigtable ChangeStream ([#1655](https://github.com/googleapis/java-bigtable/issues/1655)) ([8847fed](https://github.com/googleapis/java-bigtable/commit/8847fed7f77ce4715c197ca1cfcc3108e0fa1004)) +* Add new_partitions field for CloseStream for Cloud Bigtable ChangeStream ([#1654](https://github.com/googleapis/java-bigtable/issues/1654)) ([0e283bf](https://github.com/googleapis/java-bigtable/commit/0e283bff0a12f5e4da8b0975d4bd747229c3780c)) + + +### Bug Fixes + +* Fix StackOverflow in ChangeStreamStateMachine due to excessive mods ([#1648](https://github.com/googleapis/java-bigtable/issues/1648)) ([9e11106](https://github.com/googleapis/java-bigtable/commit/9e1110600dc64defcd9143753f45b5b8226aa339)) +* Use org.threeten.bp.Duration for ReadChangeStreamQuery::heartbeatDura… ([#1652](https://github.com/googleapis/java-bigtable/issues/1652)) ([87261a9](https://github.com/googleapis/java-bigtable/commit/87261a977d6fc7877d7d253c67ea34c264f63f7c)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-monitoring-bom to v3.13.0 ([#1656](https://github.com/googleapis/java-bigtable/issues/1656)) ([1c632ec](https://github.com/googleapis/java-bigtable/commit/1c632ec63987958e469e2b5861c29724c5cb8970)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.4.0 ([#1657](https://github.com/googleapis/java-bigtable/issues/1657)) ([c7a3e29](https://github.com/googleapis/java-bigtable/commit/c7a3e29dc717e2fa3d9b15f1ae9fb9f795d6f78a)) + ## [2.19.2](https://github.com/googleapis/java-bigtable/compare/v2.19.1...v2.19.2) (2023-02-21) diff --git a/README.md b/README.md index 46e0f520d2..72e6c23203 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file: com.google.cloud libraries-bom - 26.8.0 + 26.11.0 pom import @@ -41,7 +41,7 @@ If you are using Maven without BOM, add this to your dependencies: com.google.cloud google-cloud-bigtable - 2.19.1 + 2.20.2 ``` @@ -49,21 +49,22 @@ If you are using Maven without BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies: ```Groovy -implementation platform('com.google.cloud:libraries-bom:26.8.0') +implementation platform('com.google.cloud:libraries-bom:26.11.0') implementation 'com.google.cloud:google-cloud-bigtable' ``` If you are using Gradle without BOM, add this to your dependencies: ```Groovy -implementation 'com.google.cloud:google-cloud-bigtable:2.19.1' +implementation 'com.google.cloud:google-cloud-bigtable:2.20.2' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-bigtable" % "2.19.1" +libraryDependencies += "com.google.cloud" % "google-cloud-bigtable" % "2.20.2" ``` + ## Authentication @@ -80,7 +81,7 @@ The client application making API calls must be granted [authorization scopes][a You will need a [Google Cloud Platform Console][developer-console] project with the Cloud Bigtable [API enabled][enable-api]. [Follow these instructions][create-project] to get your project set up. You will also need to set up the local development environment by -[installing the Google Cloud SDK][cloud-sdk] and running the following commands in command line: +[installing the Google Cloud Command Line Interface][cloud-cli] and running the following commands in command line: `gcloud auth login` and `gcloud config set project [YOUR PROJECT ID]`. ### Installation and setup @@ -599,14 +600,14 @@ Java is a registered trademark of Oracle and/or its affiliates. [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-bigtable/java11.html [stability-image]: https://img.shields.io/badge/stability-stable-green [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-bigtable.svg -[maven-version-link]: https://search.maven.org/search?q=g:com.google.cloud%20AND%20a:google-cloud-bigtable&core=gav +[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-bigtable/2.20.2 [authentication]: https://github.com/googleapis/google-cloud-java#authentication [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles [iam-policy]: https://cloud.google.com/iam/docs/overview#cloud-iam-policy [developer-console]: https://console.developers.google.com/ [create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects -[cloud-sdk]: https://cloud.google.com/sdk/ +[cloud-cli]: https://cloud.google.com/cli [troubleshooting]: https://github.com/googleapis/google-cloud-common/blob/main/troubleshooting/readme.md#troubleshooting [contributing]: https://github.com/googleapis/java-bigtable/blob/main/CONTRIBUTING.md [code-of-conduct]: https://github.com/googleapis/java-bigtable/blob/main/CODE_OF_CONDUCT.md#contributor-code-of-conduct diff --git a/google-cloud-bigtable-bom/pom.xml b/google-cloud-bigtable-bom/pom.xml index 41114f8a55..9a7c6f9346 100644 --- a/google-cloud-bigtable-bom/pom.xml +++ b/google-cloud-bigtable-bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-bigtable-bom - 2.19.2 + 2.20.3 pom com.google.cloud @@ -63,42 +63,42 @@ com.google.cloud google-cloud-bigtable - 2.19.2 + 2.20.3 com.google.cloud google-cloud-bigtable-emulator - 0.156.2 + 0.157.3 com.google.cloud google-cloud-bigtable-emulator-core - 0.156.2 + 0.157.3 com.google.api.grpc grpc-google-cloud-bigtable-admin-v2 - 2.19.2 + 2.20.3 com.google.api.grpc grpc-google-cloud-bigtable-v2 - 2.19.2 + 2.20.3 com.google.api.grpc proto-google-cloud-bigtable-admin-v2 - 2.19.2 + 2.20.3 com.google.api.grpc proto-google-cloud-bigtable-v2 - 2.19.2 + 2.20.3 com.google.cloud google-cloud-bigtable-stats - 2.19.2 + 2.20.3 diff --git a/google-cloud-bigtable-deps-bom/pom.xml b/google-cloud-bigtable-deps-bom/pom.xml index 92fe1598ab..661c285d25 100644 --- a/google-cloud-bigtable-deps-bom/pom.xml +++ b/google-cloud-bigtable-deps-bom/pom.xml @@ -13,7 +13,7 @@ com.google.cloud google-cloud-bigtable-deps-bom - 2.19.2 + 2.20.3 pom @@ -66,14 +66,14 @@ com.google.cloud google-cloud-shared-dependencies - 3.3.0 + 3.6.0 pom import com.google.cloud google-cloud-monitoring-bom - 3.12.0 + 3.15.0 diff --git a/google-cloud-bigtable-emulator-core/pom.xml b/google-cloud-bigtable-emulator-core/pom.xml index 6cc932b0c2..3455de1ff1 100644 --- a/google-cloud-bigtable-emulator-core/pom.xml +++ b/google-cloud-bigtable-emulator-core/pom.xml @@ -7,11 +7,11 @@ google-cloud-bigtable-parent com.google.cloud - 2.19.2 + 2.20.3 google-cloud-bigtable-emulator-core - 0.156.2 + 0.157.3 A Java wrapper for the Cloud Bigtable emulator. diff --git a/google-cloud-bigtable-emulator/pom.xml b/google-cloud-bigtable-emulator/pom.xml index 11d99b7825..8d6da712cc 100644 --- a/google-cloud-bigtable-emulator/pom.xml +++ b/google-cloud-bigtable-emulator/pom.xml @@ -5,7 +5,7 @@ 4.0.0 google-cloud-bigtable-emulator - 0.156.2 + 0.157.3 Google Cloud Java - Bigtable Emulator https://github.com/googleapis/java-bigtable @@ -14,7 +14,7 @@ com.google.cloud google-cloud-bigtable-parent - 2.19.2 + 2.20.3 scm:git:git@github.com:googleapis/java-bigtable.git @@ -81,14 +81,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 2.19.2 + 2.20.3 pom import com.google.cloud google-cloud-bigtable-bom - 2.19.2 + 2.20.3 pom import @@ -99,7 +99,7 @@ com.google.cloud google-cloud-bigtable-emulator-core - 0.156.2 + 0.157.3 diff --git a/google-cloud-bigtable-stats/pom.xml b/google-cloud-bigtable-stats/pom.xml index acc8aa90de..a6d67db419 100644 --- a/google-cloud-bigtable-stats/pom.xml +++ b/google-cloud-bigtable-stats/pom.xml @@ -5,7 +5,7 @@ com.google.cloud google-cloud-bigtable-parent - 2.19.2 + 2.20.3 4.0.0 @@ -13,7 +13,7 @@ through Stackdriver. Built-in metrics will be implemented with shaded OpenCensus so it won't interfere with customer's application metrics. --> google-cloud-bigtable-stats - 2.19.2 + 2.20.3 Experimental project to shade OpenCensus dependencies. @@ -21,7 +21,7 @@ com.google.cloud google-cloud-bigtable-deps-bom - 2.19.2 + 2.20.3 pom import diff --git a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BigtableCreateTimeSeriesExporter.java b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BigtableCreateTimeSeriesExporter.java index ad2e76867c..325a07a0c5 100644 --- a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BigtableCreateTimeSeriesExporter.java +++ b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BigtableCreateTimeSeriesExporter.java @@ -52,35 +52,39 @@ public void export(Collection metrics) { continue; } - try { - projectToTimeSeries = - metric.getTimeSeriesList().stream() - .collect( - Collectors.groupingBy( - timeSeries -> - BigtableStackdriverExportUtils.getProjectId( - metric.getMetricDescriptor(), timeSeries), - Collectors.mapping( - timeSeries -> - BigtableStackdriverExportUtils.convertTimeSeries( - metric.getMetricDescriptor(), - timeSeries, - clientId, - monitoredResource), - Collectors.toList()))); + projectToTimeSeries = + metric.getTimeSeriesList().stream() + .collect( + Collectors.groupingBy( + timeSeries -> + BigtableStackdriverExportUtils.getProjectId( + metric.getMetricDescriptor(), timeSeries), + Collectors.mapping( + timeSeries -> + BigtableStackdriverExportUtils.convertTimeSeries( + metric.getMetricDescriptor(), + timeSeries, + clientId, + monitoredResource), + Collectors.toList()))); - for (Map.Entry> entry : - projectToTimeSeries.entrySet()) { - ProjectName projectName = ProjectName.of(entry.getKey()); - CreateTimeSeriesRequest request = - CreateTimeSeriesRequest.newBuilder() - .setName(projectName.toString()) - .addAllTimeSeries(entry.getValue()) - .build(); + for (Map.Entry> entry : + projectToTimeSeries.entrySet()) { + ProjectName projectName = ProjectName.of(entry.getKey()); + CreateTimeSeriesRequest request = + CreateTimeSeriesRequest.newBuilder() + .setName(projectName.toString()) + .addAllTimeSeries(entry.getValue()) + .build(); + try { this.metricServiceClient.createServiceTimeSeries(request); + } catch (Throwable e) { + logger.log( + Level.WARNING, + "Exception thrown when exporting TimeSeries for projectName=" + + projectName.getProject(), + e); } - } catch (Throwable e) { - logger.log(Level.WARNING, "Exception thrown when exporting TimeSeries.", e); } } } diff --git a/google-cloud-bigtable/clirr-ignored-differences.xml b/google-cloud-bigtable/clirr-ignored-differences.xml index a0ffe39bd1..da5feada67 100644 --- a/google-cloud-bigtable/clirr-ignored-differences.xml +++ b/google-cloud-bigtable/clirr-ignored-differences.xml @@ -100,6 +100,12 @@ *getStatus* com.google.cloud.bigtable.common.Status + + + 7013 + com/google/cloud/bigtable/data/v2/models/CloseStream + *getNewPartitions* + 7006 diff --git a/google-cloud-bigtable/pom.xml b/google-cloud-bigtable/pom.xml index b68fd35d8b..2c88e4d4d8 100644 --- a/google-cloud-bigtable/pom.xml +++ b/google-cloud-bigtable/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-bigtable - 2.19.2 + 2.20.3 jar Google Cloud Bigtable https://github.com/googleapis/java-bigtable @@ -12,11 +12,11 @@ com.google.cloud google-cloud-bigtable-parent - 2.19.2 + 2.20.3 - 2.19.2 + 2.20.3 google-cloud-bigtable @@ -39,7 +39,7 @@ - 1.53.0 + 1.54.0 3.21.12 ${protobuf.version} @@ -49,14 +49,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 2.19.2 + 2.20.3 pom import com.google.cloud google-cloud-bigtable-bom - 2.19.2 + 2.20.3 pom import @@ -713,7 +713,7 @@ org.codehaus.mojo extra-enforcer-rules - 1.6.1 + 1.6.2 org.apache.maven.shared @@ -746,8 +746,12 @@ true - classes - 10 + + 4 + false false diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/Version.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/Version.java index f9725f30e0..4b1988735a 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/Version.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/Version.java @@ -20,6 +20,6 @@ @InternalApi("For internal use only") public final class Version { // {x-version-update-start:google-cloud-bigtable:current} - public static String VERSION = "2.19.2"; + public static String VERSION = "2.20.3"; // {x-version-update-end} } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecord.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecord.java index edf0c1a26e..2f0233e180 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecord.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecord.java @@ -16,10 +16,11 @@ package com.google.cloud.bigtable.data.v2.models; import com.google.api.core.InternalApi; +import java.io.Serializable; /** * Default representation of a change stream record, which can be a Heartbeat, a CloseStream, or a * logical mutation. */ @InternalApi("Intended for use by the BigtableIO in apache/beam only.") -public interface ChangeStreamRecord {} +public interface ChangeStreamRecord extends Serializable {} diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/CloseStream.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/CloseStream.java index d5e121e664..344ed06c3c 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/CloseStream.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/CloseStream.java @@ -19,6 +19,8 @@ import com.google.auto.value.AutoValue; import com.google.bigtable.v2.ReadChangeStreamResponse; import com.google.cloud.bigtable.common.Status; +import com.google.cloud.bigtable.data.v2.models.Range.ByteStringRange; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import java.io.Serializable; import java.util.List; @@ -35,8 +37,23 @@ public abstract class CloseStream implements ChangeStreamRecord, Serializable { private static CloseStream create( com.google.rpc.Status status, - List changeStreamContinuationTokens) { - return new AutoValue_CloseStream(Status.fromProto(status), changeStreamContinuationTokens); + List changeStreamContinuationTokens, + List newPartitions) { + if (status.getCode() == 0) { + Preconditions.checkState( + changeStreamContinuationTokens.isEmpty(), + "An OK CloseStream should not have continuation tokens."); + } else { + Preconditions.checkState( + !changeStreamContinuationTokens.isEmpty(), + "A non-OK CloseStream should have continuation token(s)."); + Preconditions.checkState( + newPartitions.size() == 0 + || changeStreamContinuationTokens.size() == newPartitions.size(), + "Number of continuation tokens does not match number of new partitions."); + } + return new AutoValue_CloseStream( + Status.fromProto(status), changeStreamContinuationTokens, newPartitions); } /** Wraps the protobuf {@link ReadChangeStreamResponse.CloseStream}. */ @@ -46,6 +63,13 @@ public static CloseStream fromProto(@Nonnull ReadChangeStreamResponse.CloseStrea closeStream.getStatus(), closeStream.getContinuationTokensList().stream() .map(ChangeStreamContinuationToken::fromProto) + .collect(ImmutableList.toImmutableList()), + closeStream.getNewPartitionsList().stream() + .map( + newPartition -> + ByteStringRange.create( + newPartition.getRowRange().getStartKeyClosed(), + newPartition.getRowRange().getEndKeyOpen())) .collect(ImmutableList.toImmutableList())); } @@ -56,4 +80,8 @@ public static CloseStream fromProto(@Nonnull ReadChangeStreamResponse.CloseStrea @InternalApi("Intended for use by the BigtableIO in apache/beam only.") @Nonnull public abstract List getChangeStreamContinuationTokens(); + + @InternalApi("Intended for use by the BigtableIO in apache/beam only.") + @Nonnull + public abstract List getNewPartitions(); } diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQuery.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQuery.java index dc9d1fce59..a6dfb7666d 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQuery.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQuery.java @@ -182,7 +182,7 @@ public ReadChangeStreamQuery continuationTokens( } /** Sets the heartbeat duration for the change stream. */ - public ReadChangeStreamQuery heartbeatDuration(java.time.Duration duration) { + public ReadChangeStreamQuery heartbeatDuration(org.threeten.bp.Duration duration) { builder.setHeartbeatDuration( Duration.newBuilder() .setSeconds(duration.getSeconds()) diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java index 2b50224957..57c6d3337c 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStub.java @@ -395,13 +395,13 @@ public UnaryCallable createReadRowCallable(RowAdapter ReadRowsUserCallable readRowCallable = new ReadRowsUserCallable<>(readRowsCallable, requestContext); - ServerStreamingCallable traced = - new TracedServerStreamingCallable<>( - readRowCallable, clientContext.getTracerFactory(), getSpanName("ReadRow")); + ReadRowsFirstCallable firstRow = new ReadRowsFirstCallable<>(readRowCallable); - ReadRowsFirstCallable firstRow = new ReadRowsFirstCallable<>(traced); + UnaryCallable traced = + new TracedUnaryCallable<>( + firstRow, clientContext.getTracerFactory(), getSpanName("ReadRow")); - return firstRow.withDefaultCallContext(clientContext.getDefaultCallContext()); + return traced.withDefaultCallContext(clientContext.getDefaultCallContext()); } /** diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachine.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachine.java index 9654b4da30..2aa9c537db 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachine.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachine.java @@ -172,11 +172,9 @@ void handleCloseStream(ReadChangeStreamResponse.CloseStream closeStream) { *
*
Valid states: *
{@link ChangeStreamStateMachine#AWAITING_NEW_STREAM_RECORD} - *
{@link ChangeStreamStateMachine#AWAITING_NEW_MOD} - *
{@link ChangeStreamStateMachine#AWAITING_CELL_VALUE} + *
{@link ChangeStreamStateMachine#AWAITING_NEW_DATA_CHANGE} *
Resulting states: - *
{@link ChangeStreamStateMachine#AWAITING_NEW_MOD} - *
{@link ChangeStreamStateMachine#AWAITING_CELL_VALUE} + *
{@link ChangeStreamStateMachine#AWAITING_NEW_DATA_CHANGE} *
{@link ChangeStreamStateMachine#AWAITING_STREAM_RECORD_CONSUME} *
* @@ -188,7 +186,7 @@ void handleCloseStream(ReadChangeStreamResponse.CloseStream closeStream) { void handleDataChange(ReadChangeStreamResponse.DataChange dataChange) { try { numDataChanges++; - currentState = currentState.handleMod(dataChange, 0); + currentState = currentState.handleDataChange(dataChange); } catch (RuntimeException e) { currentState = ERROR; throw e; @@ -268,18 +266,17 @@ ChangeStreamStateMachine.State handleCloseStream( } /** - * Accepts a new mod and transitions to the next state. A mod could be a DeleteFamily, a - * DeleteColumn, or a SetCell. + * Accepts a new DataChange and transitions to the next state. A DataChange can have multiple + * mods, where each mod could be a DeleteFamily, a DeleteColumn, or a SetCell. * * @param dataChange The DataChange that holds the new mod to process. - * @param index The index of the mod in the DataChange. * @return The next state. - * @throws IllegalStateException If the subclass can't handle the mod. + * @throws IllegalStateException If the subclass can't handle the DataChange. * @throws ChangeStreamStateMachine.InvalidInputException If the subclass determines that this * dataChange is invalid. */ - ChangeStreamStateMachine.State handleMod( - ReadChangeStreamResponse.DataChange dataChange, int index) { + ChangeStreamStateMachine.State handleDataChange( + ReadChangeStreamResponse.DataChange dataChange) { throw new IllegalStateException(); } } @@ -292,7 +289,8 @@ ChangeStreamStateMachine.State handleMod( *
*
{@link ChangeStreamStateMachine#AWAITING_STREAM_RECORD_CONSUME}, in case of a Heartbeat * or a CloseStream. - *
Same as {@link ChangeStreamStateMachine#AWAITING_NEW_MOD}, depending on the DataChange. + *
Same as {@link ChangeStreamStateMachine#AWAITING_NEW_DATA_CHANGE}, depending on the + * DataChange. *
*/ private final State AWAITING_NEW_STREAM_RECORD = @@ -316,7 +314,7 @@ State handleCloseStream(ReadChangeStreamResponse.CloseStream closeStream) { } @Override - State handleMod(ReadChangeStreamResponse.DataChange dataChange, int index) { + State handleDataChange(ReadChangeStreamResponse.DataChange dataChange) { validate( completeChangeStreamRecord == null, "AWAITING_NEW_STREAM_RECORD: Existing ChangeStreamRecord not consumed yet."); @@ -326,9 +324,6 @@ State handleMod(ReadChangeStreamResponse.DataChange dataChange, int index) { validate( dataChange.hasCommitTimestamp(), "AWAITING_NEW_STREAM_RECORD: First data change missing commit timestamp."); - validate( - index == 0, - "AWAITING_NEW_STREAM_RECORD: First data change should start with the first mod."); validate( dataChange.getChunksCount() > 0, "AWAITING_NEW_STREAM_RECORD: First data change missing mods."); @@ -356,161 +351,138 @@ State handleMod(ReadChangeStreamResponse.DataChange dataChange, int index) { } else { validate(false, "AWAITING_NEW_STREAM_RECORD: Unexpected type: " + dataChange.getType()); } - return AWAITING_NEW_MOD.handleMod(dataChange, index); + return AWAITING_NEW_DATA_CHANGE.handleDataChange(dataChange); } }; /** - * A state to handle the next Mod. + * A state to handle the next DataChange. * *
*
Valid exit states: - *
{@link ChangeStreamStateMachine#AWAITING_NEW_MOD}. Current mod is added, and we have more - * mods to expect. - *
{@link ChangeStreamStateMachine#AWAITING_CELL_VALUE}. Current mod is the first chunk of a - * chunked SetCell. - *
{@link ChangeStreamStateMachine#AWAITING_STREAM_RECORD_CONSUME}. Current mod is the last - * mod of the current logical mutation. + *
{@link ChangeStreamStateMachine#AWAITING_NEW_DATA_CHANGE}. All mods from the current + * DataChange are added, and we have more DataChange to expect. + *
{@link ChangeStreamStateMachine#AWAITING_STREAM_RECORD_CONSUME}. Current DataChange is + * the last DataChange of the current logical mutation. *
*/ - private final State AWAITING_NEW_MOD = + private final State AWAITING_NEW_DATA_CHANGE = new State() { @Override State handleHeartbeat(ReadChangeStreamResponse.Heartbeat heartbeat) { throw new IllegalStateException( - "AWAITING_NEW_MOD: Can't handle a Heartbeat in the middle of building a ChangeStreamMutation."); + "AWAITING_NEW_DATA_CHANGE: Can't handle a Heartbeat in the middle of building a ChangeStreamMutation."); } @Override State handleCloseStream(ReadChangeStreamResponse.CloseStream closeStream) { throw new IllegalStateException( - "AWAITING_NEW_MOD: Can't handle a CloseStream in the middle of building a ChangeStreamMutation."); + "AWAITING_NEW_DATA_CHANGE: Can't handle a CloseStream in the middle of building a ChangeStreamMutation."); } @Override - State handleMod(ReadChangeStreamResponse.DataChange dataChange, int index) { - validate( - 0 <= index && index <= dataChange.getChunksCount() - 1, - "AWAITING_NEW_MOD: Index out of bound."); - ReadChangeStreamResponse.MutationChunk chunk = dataChange.getChunks(index); - Mutation mod = chunk.getMutation(); - // Case 1: SetCell - if (mod.hasSetCell()) { - // Start the Cell and delegate to AWAITING_CELL_VALUE to add the cell value. - Mutation.SetCell setCell = chunk.getMutation().getSetCell(); - if (chunk.hasChunkInfo()) { - // If it has chunk info, it must be the first chunk of a chunked SetCell. - validate( - chunk.getChunkInfo().getChunkedValueOffset() == 0, - "AWAITING_NEW_MOD: First chunk of a chunked cell must start with offset==0."); - validate( - chunk.getChunkInfo().getChunkedValueSize() > 0, - "AWAITING_NEW_MOD: First chunk of a chunked cell must have a positive chunked value size."); - expectedTotalSizeOfChunkedSetCell = chunk.getChunkInfo().getChunkedValueSize(); - actualTotalSizeOfChunkedSetCell = 0; + State handleDataChange(ReadChangeStreamResponse.DataChange dataChange) { + // Iterate over all mods. + for (int index = 0; index < dataChange.getChunksCount(); ++index) { + ReadChangeStreamResponse.MutationChunk chunk = dataChange.getChunks(index); + Mutation mod = chunk.getMutation(); + // Case 1: SetCell + if (mod.hasSetCell()) { + Mutation.SetCell setCell = chunk.getMutation().getSetCell(); + // Case 1_1: Current SetCell is NOT chunked, in which case there is no ChunkInfo. + if (!chunk.hasChunkInfo()) { + builder.startCell( + setCell.getFamilyName(), + setCell.getColumnQualifier(), + setCell.getTimestampMicros()); + numCellChunks++; + builder.cellValue(setCell.getValue()); + builder.finishCell(); + continue; + } else { + // Case 1_2: This chunk is from a chunked SetCell, which must be one of the + // following: + // Case 1_2_1: The first chunk of a chunked SetCell. For example: SetCell_chunk_1 + // in + // [ReadChangeStreamResponse1: {..., SetCell_chunk_1}, ReadChangeStreamResponse2: + // {SetCell_chunk_2, ...}]. + // Case 1_2_2: A non-first chunk from a chunked SetCell. For example: + // SetCell_chunk_2 in + // [ReadChangeStreamResponse1: {..., SetCell_chunk_1}, ReadChangeStreamResponse2: + // {SetCell_chunk_2, ...}]. Note that in this case this chunk must be the first + // chunk for the current DataChange, because a SetCell can NOT be chunked within + // the same DataChange, i.e. there is no such DataChange as + // [ReadChangeStreamResponse: {SetCell_chunk_1, SetCell_chunk_2}]. + if (chunk.getChunkInfo().getChunkedValueOffset() == 0) { + // Case 1_2_1 + validate( + chunk.getChunkInfo().getChunkedValueSize() > 0, + "AWAITING_NEW_DATA_CHANGE: First chunk of a chunked cell must have a positive chunked value size."); + expectedTotalSizeOfChunkedSetCell = chunk.getChunkInfo().getChunkedValueSize(); + actualTotalSizeOfChunkedSetCell = 0; + builder.startCell( + setCell.getFamilyName(), + setCell.getColumnQualifier(), + setCell.getTimestampMicros()); + } else { + // Case 1_2_2 + validate( + index == 0, + "AWAITING_NEW_DATA_CHANGE: Non-first chunked SetCell must be the first mod of a DataChange."); + } + // Concatenate the cell value of this mod into the builder. + validate( + chunk.getChunkInfo().getChunkedValueSize() == expectedTotalSizeOfChunkedSetCell, + "AWAITING_NEW_DATA_CHANGE: Chunked cell value size must be the same for all chunks."); + numCellChunks++; + builder.cellValue(setCell.getValue()); + actualTotalSizeOfChunkedSetCell += setCell.getValue().size(); + // If it's the last chunk of the chunked SetCell, finish the cell. + if (chunk.getChunkInfo().getLastChunk()) { + builder.finishCell(); + validate( + actualTotalSizeOfChunkedSetCell == expectedTotalSizeOfChunkedSetCell, + "Chunked value size in ChunkInfo doesn't match the actual total size. " + + "Expected total size: " + + expectedTotalSizeOfChunkedSetCell + + "; actual total size: " + + actualTotalSizeOfChunkedSetCell); + continue; + } else { + // If this is not the last chunk of a chunked SetCell, then this must be the last + // mod of the current response, and we're expecting the rest of the chunked cells + // in the following ReadChangeStream response. + validate( + index == dataChange.getChunksCount() - 1, + "AWAITING_NEW_DATA_CHANGE: Current mod is a chunked SetCell " + + "but not the last chunk, but it's not the last mod of the current response."); + return AWAITING_NEW_DATA_CHANGE; + } + } } - builder.startCell( - setCell.getFamilyName(), - setCell.getColumnQualifier(), - setCell.getTimestampMicros()); - return AWAITING_CELL_VALUE.handleMod(dataChange, index); - } - // Case 2: DeleteFamily - if (mod.hasDeleteFromFamily()) { - numNonCellMods++; - builder.deleteFamily(mod.getDeleteFromFamily().getFamilyName()); - return checkAndFinishMutationIfNeeded(dataChange, index + 1); - } - // Case 3: DeleteCell - if (mod.hasDeleteFromColumn()) { - numNonCellMods++; - builder.deleteCells( - mod.getDeleteFromColumn().getFamilyName(), - mod.getDeleteFromColumn().getColumnQualifier(), - TimestampRange.create( - mod.getDeleteFromColumn().getTimeRange().getStartTimestampMicros(), - mod.getDeleteFromColumn().getTimeRange().getEndTimestampMicros())); - return checkAndFinishMutationIfNeeded(dataChange, index + 1); - } - throw new IllegalStateException("AWAITING_NEW_MOD: Unexpected mod type"); - } - }; - - /** - * A state that represents a cell's value continuation. - * - *
- *
Valid exit states: - *
{@link ChangeStreamStateMachine#AWAITING_NEW_MOD}. Current chunked SetCell is added, and - * we have more mods to expect. - *
{@link ChangeStreamStateMachine#AWAITING_CELL_VALUE}. Current chunked SetCell has more - * cell values to expect. - *
{@link ChangeStreamStateMachine#AWAITING_STREAM_RECORD_CONSUME}. Current chunked SetCell - * is the last mod of the current logical mutation. - *
- */ - private final State AWAITING_CELL_VALUE = - new State() { - @Override - State handleHeartbeat(ReadChangeStreamResponse.Heartbeat heartbeat) { - throw new IllegalStateException( - "AWAITING_CELL_VALUE: Can't handle a Heartbeat in the middle of building a SetCell."); - } - - @Override - State handleCloseStream(ReadChangeStreamResponse.CloseStream closeStream) { - throw new IllegalStateException( - "AWAITING_CELL_VALUE: Can't handle a CloseStream in the middle of building a SetCell."); - } - - @Override - State handleMod(ReadChangeStreamResponse.DataChange dataChange, int index) { - validate( - 0 <= index && index <= dataChange.getChunksCount() - 1, - "AWAITING_CELL_VALUE: Index out of bound."); - ReadChangeStreamResponse.MutationChunk chunk = dataChange.getChunks(index); - validate( - chunk.getMutation().hasSetCell(), - "AWAITING_CELL_VALUE: Current mod is not a SetCell."); - Mutation.SetCell setCell = chunk.getMutation().getSetCell(); - numCellChunks++; - builder.cellValue(setCell.getValue()); - // Case 1: Current SetCell is chunked. For example: [ReadChangeStreamResponse1: - // {DeleteColumn, DeleteFamily, SetCell_1}, ReadChangeStreamResponse2: {SetCell_2, - // DeleteFamily}]. - if (chunk.hasChunkInfo()) { - validate( - chunk.getChunkInfo().getChunkedValueSize() > 0, - "AWAITING_CELL_VALUE: Chunked value size must be positive."); - validate( - chunk.getChunkInfo().getChunkedValueSize() == expectedTotalSizeOfChunkedSetCell, - "AWAITING_CELL_VALUE: Chunked value size must be the same for all chunks."); - actualTotalSizeOfChunkedSetCell += setCell.getValue().size(); - // If it's the last chunk of the chunked SetCell, finish the cell. - if (chunk.getChunkInfo().getLastChunk()) { - builder.finishCell(); - validate( - actualTotalSizeOfChunkedSetCell == expectedTotalSizeOfChunkedSetCell, - "Chunked value size in ChunkInfo doesn't match the actual total size. " - + "Expected total size: " - + expectedTotalSizeOfChunkedSetCell - + "; actual total size: " - + actualTotalSizeOfChunkedSetCell); - return checkAndFinishMutationIfNeeded(dataChange, index + 1); - } else { - // If this is not the last chunk of a chunked SetCell, then this must be the last mod - // of the current response, and we're expecting the rest of the chunked cells in the - // following ReadChangeStream response. - validate( - index == dataChange.getChunksCount() - 1, - "AWAITING_CELL_VALUE: Current mod is a chunked SetCell " - + "but not the last chunk, but it's not the last mod of the current response."); - return AWAITING_CELL_VALUE; + // Case 2: DeleteFamily + if (mod.hasDeleteFromFamily()) { + numNonCellMods++; + builder.deleteFamily(mod.getDeleteFromFamily().getFamilyName()); + continue; + } + // Case 3: DeleteCell + if (mod.hasDeleteFromColumn()) { + numNonCellMods++; + builder.deleteCells( + mod.getDeleteFromColumn().getFamilyName(), + mod.getDeleteFromColumn().getColumnQualifier(), + TimestampRange.create( + mod.getDeleteFromColumn().getTimeRange().getStartTimestampMicros(), + mod.getDeleteFromColumn().getTimeRange().getEndTimestampMicros())); + continue; } + throw new IllegalStateException("AWAITING_NEW_DATA_CHANGE: Unexpected mod type"); } - // Case 2: Current SetCell is not chunked. - builder.finishCell(); - return checkAndFinishMutationIfNeeded(dataChange, index + 1); + + // After adding all mods from this DataChange to the state machine, finish the current + // logical mutation, or wait for the next DataChange response. + return checkAndFinishMutationIfNeeded(dataChange); } }; @@ -535,7 +507,7 @@ State handleCloseStream(ReadChangeStreamResponse.CloseStream closeStream) { } @Override - State handleMod(ReadChangeStreamResponse.DataChange dataChange, int index) { + State handleDataChange(ReadChangeStreamResponse.DataChange dataChange) { throw new IllegalStateException( "AWAITING_STREAM_RECORD_CONSUME: Skipping completed change stream record."); } @@ -558,39 +530,29 @@ State handleCloseStream(ReadChangeStreamResponse.CloseStream closeStream) { } @Override - State handleMod(ReadChangeStreamResponse.DataChange dataChange, int index) { + State handleDataChange(ReadChangeStreamResponse.DataChange dataChange) { throw new IllegalStateException("ERROR: Failed to handle DataChange."); } }; /** - * Check if we should continue handling mods in the current DataChange or wrap up. There are 3 - * cases: + * Check if we should continue handling DataChanges in the following responses or wrap up. There + * are 2 cases: * *
    - *
  • 1) index < dataChange.getChunksCount() -> continue to handle the next mod. - *
  • 2_1) index == dataChange.getChunksCount() && dataChange.done == true -> current change - * stream mutation is complete. Wrap it up and return {@link - * ChangeStreamStateMachine#AWAITING_STREAM_RECORD_CONSUME}. - *
  • 2_2) index == dataChange.getChunksCount() && dataChange.done != true -> current change - * stream mutation isn't complete. Return {@link ChangeStreamStateMachine#AWAITING_NEW_MOD} - * to wait for more mods in the next ReadChangeStreamResponse. + *
  • 1) dataChange.done == true -> current change stream mutation is complete. Wrap it up and + * return {@link ChangeStreamStateMachine#AWAITING_STREAM_RECORD_CONSUME}. + *
  • 2) dataChange.done != true -> current change stream mutation isn't complete. Return + * {@link ChangeStreamStateMachine#AWAITING_NEW_DATA_CHANGE} to wait for more mods in the + * next ReadChangeStreamResponse. *
*/ - private State checkAndFinishMutationIfNeeded( - ReadChangeStreamResponse.DataChange dataChange, int index) { - validate( - 0 <= index && index <= dataChange.getChunksCount(), - "checkAndFinishMutationIfNeeded: index out of bound."); - // Case 1): Handle the next mod. - if (index < dataChange.getChunksCount()) { - return AWAITING_NEW_MOD.handleMod(dataChange, index); - } - // If we reach here, it means that all the mods in this DataChange have been handled. We should + private State checkAndFinishMutationIfNeeded(ReadChangeStreamResponse.DataChange dataChange) { + // This function is called when all the mods in this DataChange have been handled. We should // finish up the logical mutation or wait for more mods in the next ReadChangeStreamResponse, // depending on whether the current response is the last response for the logical mutation. if (dataChange.getDone()) { - // Case 2_1): Current change stream mutation is complete. + // Case 1: Current change stream mutation is complete. validate(!dataChange.getToken().isEmpty(), "Last data change missing token"); validate(dataChange.hasEstimatedLowWatermark(), "Last data change missing lowWatermark"); completeChangeStreamRecord = @@ -601,10 +563,10 @@ private State checkAndFinishMutationIfNeeded( dataChange.getEstimatedLowWatermark().getNanos())); return AWAITING_STREAM_RECORD_CONSUME; } - // Case 2_2): The current DataChange itself is chunked, so wait for the next - // ReadChangeStreamResponse. Note that we should wait for the new mods instead + // Case 2: The current DataChange itself is chunked, so wait for the next + // ReadChangeStreamResponse. Note that we should wait for the new data change instead // of for the new change stream record since the current record hasn't finished yet. - return AWAITING_NEW_MOD; + return AWAITING_NEW_DATA_CHANGE; } private void validate(boolean condition, String message) { diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamResumptionStrategy.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamResumptionStrategy.java index 660466db95..fda608eda5 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamResumptionStrategy.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamResumptionStrategy.java @@ -56,7 +56,13 @@ public StreamResumptionStrategy cr public ChangeStreamRecordT processResponse(ChangeStreamRecordT response) { // Update the token from a Heartbeat or a ChangeStreamMutation. // We don't worry about resumption after CloseStream, since the server - // will return an OK status right after sending a CloseStream. + // will close the stream with an OK status right after sending a CloseStream, + // no matter what status the CloseStream.Status is: + // 1) ... => CloseStream.Ok => final OK. This means the read finishes successfully. + // 2) ... => CloseStream.Error => final OK. This means the client should start + // a new ReadChangeStream call with the continuation tokens specified in + // CloseStream. + // Either case, we don't need to retry after receiving a CloseStream. if (changeStreamRecordAdapter.isHeartbeat(response)) { this.token = changeStreamRecordAdapter.getTokenFromHeartbeat(response); } else if (changeStreamRecordAdapter.isChangeStreamMutation(response)) { diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracer.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracer.java index cb3791360a..e592d0038f 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracer.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracer.java @@ -55,7 +55,7 @@ class BuiltinMetricsTracer extends BigtableTracer { // Total server latency needs to be atomic because it's accessed from different threads. E.g. // request() from user thread and attempt failed from grpc thread. We're only measuring the extra // time application spent blocking grpc buffer, which will be operationLatency - serverLatency. - private final AtomicLong totalServerLatency = new AtomicLong(0); + private final AtomicLong totalServerLatencyNano = new AtomicLong(0); // Stopwatch is not thread safe so this is a workaround to check if the stopwatch changes is // flushed to memory. private final Stopwatch serverLatencyTimer = Stopwatch.createUnstarted(); @@ -171,7 +171,7 @@ public void responseReceived() { // In all the cases, we want to stop the serverLatencyTimer here. synchronized (timerLock) { if (serverLatencyTimerIsRunning) { - totalServerLatency.addAndGet(serverLatencyTimer.elapsed(TimeUnit.MILLISECONDS)); + totalServerLatencyNano.addAndGet(serverLatencyTimer.elapsed(TimeUnit.NANOSECONDS)); serverLatencyTimer.reset(); serverLatencyTimerIsRunning = false; } @@ -233,6 +233,7 @@ private void recordOperationCompletion(@Nullable Throwable status) { } operationTimer.stop(); long operationLatency = operationTimer.elapsed(TimeUnit.MILLISECONDS); + long operationLatencyNano = operationTimer.elapsed(TimeUnit.NANOSECONDS); // Only record when retry count is greater than 0 so the retry // graph will be less confusing @@ -242,7 +243,8 @@ private void recordOperationCompletion(@Nullable Throwable status) { // serverLatencyTimer should already be stopped in recordAttemptCompletion recorder.putOperationLatencies(operationLatency); - recorder.putApplicationLatencies(operationLatency - totalServerLatency.get()); + recorder.putApplicationLatencies( + Duration.ofNanos(operationLatencyNano - totalServerLatencyNano.get()).toMillis()); if (operationType == OperationType.ServerStreaming && spanName.getMethodName().equals("ReadRows")) { @@ -258,7 +260,7 @@ private void recordAttemptCompletion(@Nullable Throwable status) { synchronized (timerLock) { if (serverLatencyTimerIsRunning) { requestLeft.decrementAndGet(); - totalServerLatency.addAndGet(serverLatencyTimer.elapsed(TimeUnit.MILLISECONDS)); + totalServerLatencyNano.addAndGet(serverLatencyTimer.elapsed(TimeUnit.NANOSECONDS)); serverLatencyTimer.reset(); serverLatencyTimerIsRunning = false; } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/BuiltinMetricsIT.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/BuiltinMetricsIT.java index e55f3a160d..4e75fb8631 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/BuiltinMetricsIT.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/BuiltinMetricsIT.java @@ -15,36 +15,52 @@ */ package com.google.cloud.bigtable.data.v2.it; -import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.TruthJUnit.assume; import com.google.api.client.util.Lists; +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; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; import com.google.cloud.bigtable.data.v2.models.Query; import com.google.cloud.bigtable.data.v2.models.Row; import com.google.cloud.bigtable.data.v2.models.RowMutation; import com.google.cloud.bigtable.test_helpers.env.EmulatorEnv; +import com.google.cloud.bigtable.test_helpers.env.PrefixGenerator; import com.google.cloud.bigtable.test_helpers.env.TestEnvRule; import com.google.cloud.monitoring.v3.MetricServiceClient; +import com.google.common.base.Stopwatch; import com.google.monitoring.v3.ListTimeSeriesRequest; import com.google.monitoring.v3.ListTimeSeriesResponse; import com.google.monitoring.v3.ProjectName; import com.google.monitoring.v3.TimeInterval; import com.google.protobuf.util.Timestamps; import java.io.IOException; -import java.time.Duration; import java.util.ArrayList; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.Timeout; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.threeten.bp.Duration; @RunWith(JUnit4.class) public class BuiltinMetricsIT { @ClassRule public static TestEnvRule testEnvRule = new TestEnvRule(); - public static MetricServiceClient metricClient; + + private static final Logger logger = Logger.getLogger(BuiltinMetricsIT.class.getName()); + + @Rule public Timeout globalTimeout = Timeout.seconds(900); + private static Table table; + private static BigtableTableAdminClient tableAdminClient; + private static MetricServiceClient metricClient; public static String[] VIEWS = { "operation_latencies", @@ -65,6 +81,8 @@ public static void setUpClass() throws IOException { // Create a cloud monitoring client metricClient = MetricServiceClient.create(); + + tableAdminClient = testEnvRule.env().getTableAdminClient(); } @AfterClass @@ -72,35 +90,39 @@ public static void tearDown() { if (metricClient != null) { metricClient.close(); } + if (table != null) { + tableAdminClient.deleteTable(table.getId()); + } } @Test public void testBuiltinMetrics() throws Exception { + logger.info("Started testing builtin metrics"); + table = + tableAdminClient.createTable( + CreateTableRequest.of(PrefixGenerator.newPrefix("BuiltinMetricsIT#test")) + .addFamily("cf")); + logger.info("Create table: " + table.getId()); // Send a MutateRow and ReadRows request testEnvRule .env() .getDataClient() - .mutateRow( - RowMutation.create(testEnvRule.env().getTableId(), "a-new-key") - .setCell(testEnvRule.env().getFamilyId(), "q", "abc")); + .mutateRow(RowMutation.create(table.getId(), "a-new-key").setCell("cf", "q", "abc")); ArrayList rows = Lists.newArrayList( - testEnvRule - .env() - .getDataClient() - .readRows(Query.create(testEnvRule.env().getTableId()).limit(10))); + testEnvRule.env().getDataClient().readRows(Query.create(table.getId()).limit(10))); - // Sleep 5 minutes so the metrics could be published and precomputation is done - Thread.sleep(Duration.ofMinutes(5).toMillis()); + Stopwatch stopwatch = Stopwatch.createStarted(); ProjectName name = ProjectName.of(testEnvRule.env().getProjectId()); - // Restrict time to last 10 minutes + // Restrict time to last 10 minutes and 5 minutes after the request long startMillis = System.currentTimeMillis() - Duration.ofMinutes(10).toMillis(); + long endMillis = startMillis + Duration.ofMinutes(15).toMillis(); TimeInterval interval = TimeInterval.newBuilder() .setStartTime(Timestamps.fromMillis(startMillis)) - .setEndTime(Timestamps.fromMillis(System.currentTimeMillis())) + .setEndTime(Timestamps.fromMillis(endMillis)) .build(); for (String view : VIEWS) { @@ -109,27 +131,50 @@ public void testBuiltinMetrics() throws Exception { String metricFilter = String.format( "metric.type=\"bigtable.googleapis.com/client/%s\" " - + "AND resource.labels.instance=\"%s\" AND metric.labels.method=\"Bigtable.MutateRow\"", - view, testEnvRule.env().getInstanceId()); + + "AND resource.labels.instance=\"%s\" AND metric.labels.method=\"Bigtable.MutateRow\"" + + " AND resource.labels.table=\"%s\"", + view, testEnvRule.env().getInstanceId(), table.getId()); ListTimeSeriesRequest.Builder requestBuilder = ListTimeSeriesRequest.newBuilder() .setName(name.toString()) .setFilter(metricFilter) .setInterval(interval) .setView(ListTimeSeriesRequest.TimeSeriesView.FULL); - ListTimeSeriesResponse response = - metricClient.listTimeSeriesCallable().call(requestBuilder.build()); - assertThat(response.getTimeSeriesCount()).isGreaterThan(0); + + verifyMetricsArePublished(requestBuilder.build(), stopwatch, view); // Verify that metrics are published for ReadRows request metricFilter = String.format( "metric.type=\"bigtable.googleapis.com/client/%s\" " - + "AND resource.labels.instance=\"%s\" AND metric.labels.method=\"Bigtable.ReadRows\"", - view, testEnvRule.env().getInstanceId()); + + "AND resource.labels.instance=\"%s\" AND metric.labels.method=\"Bigtable.ReadRows\"" + + " AND resource.labels.table=\"%s\"", + view, testEnvRule.env().getInstanceId(), table.getId()); requestBuilder.setFilter(metricFilter); - response = metricClient.listTimeSeriesCallable().call(requestBuilder.build()); - assertThat(response.getTimeSeriesCount()).isGreaterThan(0); + + verifyMetricsArePublished(requestBuilder.build(), stopwatch, view); } } + + private void verifyMetricsArePublished( + ListTimeSeriesRequest request, Stopwatch stopwatch, String view) throws Exception { + ListTimeSeriesResponse response = metricClient.listTimeSeriesCallable().call(request); + logger.log( + Level.INFO, + "Checking for view " + + view + + ", has timeseries=" + + response.getTimeSeriesCount() + + " stopwatch elapsed " + + stopwatch.elapsed(TimeUnit.MINUTES)); + while (response.getTimeSeriesCount() == 0 && stopwatch.elapsed(TimeUnit.MINUTES) < 10) { + // Call listTimeSeries every minute + Thread.sleep(Duration.ofMinutes(1).toMillis()); + response = metricClient.listTimeSeriesCallable().call(request); + } + + assertWithMessage("View " + view + " didn't return any data.") + .that(response.getTimeSeriesCount()) + .isGreaterThan(0); + } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecordTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecordTest.java index 688ce46bcf..3f09d9b443 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecordTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ChangeStreamRecordTest.java @@ -30,7 +30,11 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.function.ThrowingRunnable; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.threeten.bp.Instant; @@ -38,6 +42,8 @@ @RunWith(JUnit4.class) public class ChangeStreamRecordTest { + @Rule public ExpectedException expect = ExpectedException.none(); + @Test public void heartbeatSerializationTest() throws IOException, ClassNotFoundException { ReadChangeStreamResponse.Heartbeat heartbeatProto = @@ -60,7 +66,7 @@ public void heartbeatSerializationTest() throws IOException, ClassNotFoundExcept @Test public void closeStreamSerializationTest() throws IOException, ClassNotFoundException { - Status status = Status.newBuilder().setCode(0).build(); + Status status = Status.newBuilder().setCode(11).build(); RowRange rowRange1 = RowRange.newBuilder() .setStartKeyClosed(ByteString.copyFromUtf8("")) @@ -85,6 +91,8 @@ public void closeStreamSerializationTest() throws IOException, ClassNotFoundExce .setPartition(StreamPartition.newBuilder().setRowRange(rowRange2).build()) .setToken(token2) .build()) + .addNewPartitions(StreamPartition.newBuilder().setRowRange(rowRange1)) + .addNewPartitions(StreamPartition.newBuilder().setRowRange(rowRange2)) .setStatus(status) .build(); CloseStream closeStream = CloseStream.fromProto(closeStreamProto); @@ -98,6 +106,7 @@ public void closeStreamSerializationTest() throws IOException, ClassNotFoundExce assertThat(actual.getChangeStreamContinuationTokens()) .isEqualTo(closeStream.getChangeStreamContinuationTokens()); assertThat(actual.getStatus()).isEqualTo(closeStream.getStatus()); + assertThat(actual.getNewPartitions()).isEqualTo(closeStream.getNewPartitions()); } @Test @@ -129,7 +138,7 @@ public void heartbeatTest() { @Test public void closeStreamTest() { - Status status = Status.newBuilder().setCode(0).build(); + Status status = Status.newBuilder().setCode(11).build(); RowRange rowRange1 = RowRange.newBuilder() .setStartKeyClosed(ByteString.copyFromUtf8("")) @@ -154,6 +163,8 @@ public void closeStreamTest() { .setPartition(StreamPartition.newBuilder().setRowRange(rowRange2).build()) .setToken(token2) .build()) + .addNewPartitions(StreamPartition.newBuilder().setRowRange(rowRange1)) + .addNewPartitions(StreamPartition.newBuilder().setRowRange(rowRange2)) .setStatus(status) .build(); CloseStream actualCloseStream = CloseStream.fromProto(closeStreamProto); @@ -169,5 +180,101 @@ public void closeStreamTest() { ByteStringRange.create(rowRange2.getStartKeyClosed(), rowRange2.getEndKeyOpen())); assertThat(token2) .isEqualTo(actualCloseStream.getChangeStreamContinuationTokens().get(1).getToken()); + assertThat(actualCloseStream.getNewPartitions().get(0)) + .isEqualTo( + ByteStringRange.create(rowRange1.getStartKeyClosed(), rowRange1.getEndKeyOpen())); + assertThat(actualCloseStream.getNewPartitions().get(1)) + .isEqualTo( + ByteStringRange.create(rowRange2.getStartKeyClosed(), rowRange2.getEndKeyOpen())); + } + + // Tests that an OK CloseStream should not have continuation tokens. + @Test(expected = IllegalStateException.class) + public void closeStreamOkWithContinuationTokenShouldFail() { + Status status = Status.newBuilder().setCode(0).build(); + RowRange rowRange = + RowRange.newBuilder() + .setStartKeyClosed(ByteString.copyFromUtf8("")) + .setEndKeyOpen(ByteString.copyFromUtf8("apple")) + .build(); + String token = "close-stream-token-1"; + ReadChangeStreamResponse.CloseStream closeStreamProto = + ReadChangeStreamResponse.CloseStream.newBuilder() + .addContinuationTokens( + StreamContinuationToken.newBuilder() + .setPartition(StreamPartition.newBuilder().setRowRange(rowRange)) + .setToken(token)) + .setStatus(status) + .build(); + Assert.assertThrows( + IllegalStateException.class, (ThrowingRunnable) CloseStream.fromProto(closeStreamProto)); + } + + // Tests that a non-OK CloseStream should have continuation tokens. + @Test(expected = IllegalStateException.class) + public void closeStreamErrorWithoutContinuationTokenShouldFail() { + Status status = Status.newBuilder().setCode(11).build(); + ReadChangeStreamResponse.CloseStream closeStreamProto = + ReadChangeStreamResponse.CloseStream.newBuilder().setStatus(status).build(); + Assert.assertThrows( + IllegalStateException.class, (ThrowingRunnable) CloseStream.fromProto(closeStreamProto)); + } + + // Tests that the number of continuation tokens should match the number of new partitions. + @Test(expected = IllegalStateException.class) + public void closeStreamTokenAndNewPartitionCountMismatchedTest() { + Status status = Status.newBuilder().setCode(11).build(); + RowRange rowRange = + RowRange.newBuilder() + .setStartKeyClosed(ByteString.copyFromUtf8("")) + .setEndKeyOpen(ByteString.copyFromUtf8("apple")) + .build(); + String token = "close-stream-token-1"; + ReadChangeStreamResponse.CloseStream closeStreamProto = + ReadChangeStreamResponse.CloseStream.newBuilder() + .addContinuationTokens( + StreamContinuationToken.newBuilder() + .setPartition(StreamPartition.newBuilder().setRowRange(rowRange)) + .setToken(token)) + .addNewPartitions(StreamPartition.newBuilder().setRowRange(rowRange)) + .addNewPartitions(StreamPartition.newBuilder().setRowRange(rowRange)) + .setStatus(status) + .build(); + Assert.assertThrows( + IllegalStateException.class, (ThrowingRunnable) CloseStream.fromProto(closeStreamProto)); + } + + // Tests that number of continuation tokens and new partitions don't need to match if new + // partitions is empty. + @Test + public void closeStreamTokenAndZeroNewPartitionMismatchNoExceptionTest() + throws IOException, ClassNotFoundException { + Status status = Status.newBuilder().setCode(11).build(); + RowRange rowRange = + RowRange.newBuilder() + .setStartKeyClosed(ByteString.copyFromUtf8("")) + .setEndKeyOpen(ByteString.copyFromUtf8("apple")) + .build(); + String token = "close-stream-token-1"; + ReadChangeStreamResponse.CloseStream closeStreamProto = + ReadChangeStreamResponse.CloseStream.newBuilder() + .addContinuationTokens( + StreamContinuationToken.newBuilder() + .setPartition(StreamPartition.newBuilder().setRowRange(rowRange)) + .setToken(token)) + .setStatus(status) + .build(); + CloseStream closeStream = CloseStream.fromProto(closeStreamProto); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(closeStream); + oos.close(); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); + CloseStream actual = (CloseStream) ois.readObject(); + assertThat(actual.getChangeStreamContinuationTokens()) + .isEqualTo(closeStream.getChangeStreamContinuationTokens()); + assertThat(actual.getStatus()).isEqualTo(closeStream.getStatus()); + assertThat(actual.getNewPartitions()).isEqualTo(closeStream.getNewPartitions()); } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/DefaultChangeStreamRecordAdapterTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/DefaultChangeStreamRecordAdapterTest.java index 99af76fb03..22270bc269 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/DefaultChangeStreamRecordAdapterTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/DefaultChangeStreamRecordAdapterTest.java @@ -150,8 +150,6 @@ public void heartbeatTest() { public void closeStreamTest() { ReadChangeStreamResponse.CloseStream expectedCloseStream = ReadChangeStreamResponse.CloseStream.newBuilder() - .addContinuationTokens( - StreamContinuationToken.newBuilder().setToken("random-token").build()) .setStatus(Status.newBuilder().setCode(0).build()) .build(); assertThat(changeStreamRecordBuilder.onCloseStream(expectedCloseStream)) diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQueryTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQueryTest.java index 79a0f72b2b..699f60a8d1 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQueryTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ReadChangeStreamQueryTest.java @@ -152,11 +152,11 @@ public void endTimeTest() { @Test public void heartbeatDurationTest() { ReadChangeStreamQuery query = - ReadChangeStreamQuery.create(TABLE_ID).heartbeatDuration(java.time.Duration.ofSeconds(5)); + ReadChangeStreamQuery.create(TABLE_ID) + .heartbeatDuration(org.threeten.bp.Duration.ofSeconds(5)); Builder expectedProto = - expectedProtoBuilder() - .setHeartbeatDuration(com.google.protobuf.Duration.newBuilder().setSeconds(5).build()); + expectedProtoBuilder().setHeartbeatDuration(Duration.newBuilder().setSeconds(5).build()); ReadChangeStreamRequest actualProto = query.toProto(requestContext); assertThat(actualProto).isEqualTo(expectedProto.build()); @@ -232,7 +232,7 @@ public void serializationTest() throws IOException, ClassNotFoundException { .streamPartition("simple-begin", "simple-end") .continuationTokens(Collections.singletonList(token)) .endTime(FAKE_END_TIME) - .heartbeatDuration(java.time.Duration.ofSeconds(5)); + .heartbeatDuration(org.threeten.bp.Duration.ofSeconds(5)); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); @@ -302,7 +302,7 @@ public void testEquality() { .streamPartition("simple-begin", "simple-end") .startTime(FAKE_START_TIME) .endTime(FAKE_END_TIME) - .heartbeatDuration(java.time.Duration.ofSeconds(5)); + .heartbeatDuration(org.threeten.bp.Duration.ofSeconds(5)); // ReadChangeStreamQuery#toProto should not change the ReadChangeStreamQuery instance state request.toProto(requestContext); @@ -312,7 +312,7 @@ public void testEquality() { .streamPartition("simple-begin", "simple-end") .startTime(FAKE_START_TIME) .endTime(FAKE_END_TIME) - .heartbeatDuration(java.time.Duration.ofSeconds(5))); + .heartbeatDuration(org.threeten.bp.Duration.ofSeconds(5))); assertThat(ReadChangeStreamQuery.create(TABLE_ID).streamPartition("begin-1", "end-1")) .isNotEqualTo(ReadChangeStreamQuery.create(TABLE_ID).streamPartition("begin-2", "end-1")); @@ -324,10 +324,10 @@ public void testEquality() { ReadChangeStreamQuery.create(TABLE_ID).endTime(Instant.ofEpochSecond(1L, 1001L))); assertThat( ReadChangeStreamQuery.create(TABLE_ID) - .heartbeatDuration(java.time.Duration.ofSeconds(5))) + .heartbeatDuration(org.threeten.bp.Duration.ofSeconds(5))) .isNotEqualTo( ReadChangeStreamQuery.create(TABLE_ID) - .heartbeatDuration(java.time.Duration.ofSeconds(6))); + .heartbeatDuration(org.threeten.bp.Duration.ofSeconds(6))); } @Test @@ -350,7 +350,7 @@ public void testClone() { .streamPartition("begin", "end") .continuationTokens(Collections.singletonList(token)) .endTime(FAKE_END_TIME) - .heartbeatDuration(java.time.Duration.ofSeconds(5)); + .heartbeatDuration(org.threeten.bp.Duration.ofSeconds(5)); ReadChangeStreamRequest request = ReadChangeStreamRequest.newBuilder() .setTableName(NameUtil.formatTableName(PROJECT_ID, INSTANCE_ID, TABLE_ID)) diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamRecordMergingCallableTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamRecordMergingCallableTest.java index 736491a0af..f0939fb0cf 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamRecordMergingCallableTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamRecordMergingCallableTest.java @@ -102,7 +102,8 @@ public void closeStreamTest() { ReadChangeStreamResponse.CloseStream closeStreamProto = ReadChangeStreamResponse.CloseStream.newBuilder() .addContinuationTokens(streamContinuationToken) - .setStatus(Status.newBuilder().setCode(0).build()) + .addNewPartitions(StreamPartition.newBuilder().setRowRange(rowRange)) + .setStatus(Status.newBuilder().setCode(11)) .build(); ReadChangeStreamResponse response = ReadChangeStreamResponse.newBuilder().setCloseStream(closeStreamProto).build(); @@ -127,5 +128,8 @@ public void closeStreamTest() { .isEqualTo(ByteStringRange.create(rowRange.getStartKeyClosed(), rowRange.getEndKeyOpen())); assertThat(changeStreamContinuationToken.getToken()) .isEqualTo(streamContinuationToken.getToken()); + assertThat(closeStream.getNewPartitions().size()).isEqualTo(1); + assertThat(closeStream.getNewPartitions().get(0)) + .isEqualTo(ByteStringRange.create(rowRange.getStartKeyClosed(), rowRange.getEndKeyOpen())); } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachineTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachineTest.java index d86df91c35..b51194f969 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachineTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ChangeStreamStateMachineTest.java @@ -17,9 +17,13 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.bigtable.v2.Mutation; import com.google.bigtable.v2.ReadChangeStreamResponse; +import com.google.cloud.bigtable.data.v2.models.ChangeStreamMutation; import com.google.cloud.bigtable.data.v2.models.ChangeStreamRecord; import com.google.cloud.bigtable.data.v2.models.DefaultChangeStreamRecordAdapter; +import com.google.protobuf.ByteString; +import com.google.protobuf.Timestamp; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,6 +33,30 @@ public class ChangeStreamStateMachineTest { ChangeStreamStateMachine changeStreamStateMachine; + private ReadChangeStreamResponse.DataChange createDataChangeWithDeleteFamilyMods( + int numDeleteFamilyMod) { + ReadChangeStreamResponse.DataChange.Builder dataChangeBuilder = + ReadChangeStreamResponse.DataChange.newBuilder() + .setType(ReadChangeStreamResponse.DataChange.Type.USER) + .setSourceClusterId("fake-source-cluster-id") + .setRowKey(ByteString.copyFromUtf8("key")) + .setCommitTimestamp(Timestamp.newBuilder().setSeconds(100).build()) + .setTiebreaker(100); + for (int i = 0; i < numDeleteFamilyMod; ++i) { + Mutation deleteFromFamily = + Mutation.newBuilder() + .setDeleteFromFamily( + Mutation.DeleteFromFamily.newBuilder().setFamilyName("fake-family-" + i).build()) + .build(); + dataChangeBuilder.addChunks( + ReadChangeStreamResponse.MutationChunk.newBuilder().setMutation(deleteFromFamily)); + } + dataChangeBuilder.setDone(true); + dataChangeBuilder.setEstimatedLowWatermark(Timestamp.newBuilder().setSeconds(1).build()); + dataChangeBuilder.setToken("fake-token"); + return dataChangeBuilder.build(); + } + @Before public void setUp() throws Exception { changeStreamStateMachine = @@ -58,4 +86,12 @@ public void testErrorHandlingStats() { assertThat(actualError).hasMessageThat().contains("numCellChunks: 0"); assertThat(actualError).hasMessageThat().contains("actualTotalSizeOfChunkedSetCell: 0"); } + + @Test + public void testNoStackOverflowForManyMods() { + ReadChangeStreamResponse.DataChange dataChange = createDataChangeWithDeleteFamilyMods(500000); + changeStreamStateMachine.handleDataChange(dataChange); + ChangeStreamRecord result = changeStreamStateMachine.consumeChangeStreamRecord(); + assertThat(result instanceof ChangeStreamMutation); + } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamMergingAcceptanceTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamMergingAcceptanceTest.java index 67d6a99f7b..7c3243ecfe 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamMergingAcceptanceTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamMergingAcceptanceTest.java @@ -38,6 +38,7 @@ import com.google.cloud.bigtable.data.v2.models.DeleteFamily; import com.google.cloud.bigtable.data.v2.models.Entry; import com.google.cloud.bigtable.data.v2.models.Heartbeat; +import com.google.cloud.bigtable.data.v2.models.Range.ByteStringRange; import com.google.cloud.bigtable.data.v2.models.SetCell; import com.google.cloud.bigtable.gaxx.testing.FakeStreamingApi; import com.google.cloud.conformance.bigtable.v2.ChangeStreamTestDefinition.ChangeStreamTestFile; @@ -173,6 +174,14 @@ public void test() throws Exception { .setToken(token.getToken()) .build()); } + for (ByteStringRange newPartition : closeStream.getNewPartitions()) { + builder.addNewPartitions( + StreamPartition.newBuilder() + .setRowRange( + RowRange.newBuilder() + .setStartKeyClosed(newPartition.getStart()) + .setEndKeyOpen(newPartition.getEnd()))); + } ReadChangeStreamResponse.CloseStream closeStreamProto = builder.build(); actualResults.add( ReadChangeStreamTest.Result.newBuilder() diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamRetryTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamRetryTest.java index c994f3fc8d..48a62bfee8 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamRetryTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamRetryTest.java @@ -122,6 +122,15 @@ private StreamContinuationToken createStreamContinuationToken(@Nonnull String to .build(); } + private StreamPartition createNewPartitionForCloseStream() { + return StreamPartition.newBuilder() + .setRowRange( + RowRange.newBuilder() + .setStartKeyClosed(ByteString.copyFromUtf8(START_KEY_CLOSED)) + .setEndKeyOpen(ByteString.copyFromUtf8(END_KEY_OPEN))) + .build(); + } + private ReadChangeStreamResponse.Heartbeat createHeartbeat( StreamContinuationToken streamContinuationToken) { return ReadChangeStreamResponse.Heartbeat.newBuilder() @@ -130,11 +139,18 @@ private ReadChangeStreamResponse.Heartbeat createHeartbeat( .build(); } - private ReadChangeStreamResponse.CloseStream createCloseStream() { - return ReadChangeStreamResponse.CloseStream.newBuilder() - .addContinuationTokens(createStreamContinuationToken(CLOSE_STREAM_TOKEN)) - .setStatus(com.google.rpc.Status.newBuilder().setCode(0).build()) - .build(); + private ReadChangeStreamResponse.CloseStream createCloseStream(boolean isOk) { + ReadChangeStreamResponse.CloseStream.Builder builder = + ReadChangeStreamResponse.CloseStream.newBuilder(); + if (isOk) { + builder.setStatus(com.google.rpc.Status.newBuilder().setCode(0)); + } else { + builder + .setStatus(com.google.rpc.Status.newBuilder().setCode(11)) + .addContinuationTokens(createStreamContinuationToken(CLOSE_STREAM_TOKEN)) + .addNewPartitions(createNewPartitionForCloseStream()); + } + return builder.build(); } private ReadChangeStreamResponse.DataChange createDataChange(boolean done) { @@ -178,7 +194,7 @@ public void happyPathHeartbeatTest() { @Test public void happyPathCloseStreamTest() { ReadChangeStreamResponse closeStreamResponse = - ReadChangeStreamResponse.newBuilder().setCloseStream(createCloseStream()).build(); + ReadChangeStreamResponse.newBuilder().setCloseStream(createCloseStream(true)).build(); service.expectations.add( RpcExpectation.create().expectInitialRequest().respondWith(closeStreamResponse)); List actualResults = getResults(); @@ -221,7 +237,7 @@ public void singleHeartbeatImmediateRetryTest() { public void singleCloseStreamImmediateRetryTest() { // CloseStream. ReadChangeStreamResponse closeStreamResponse = - ReadChangeStreamResponse.newBuilder().setCloseStream(createCloseStream()).build(); + ReadChangeStreamResponse.newBuilder().setCloseStream(createCloseStream(false)).build(); service.expectations.add( RpcExpectation.create().expectInitialRequest().respondWithStatus(Code.UNAVAILABLE)); // Resume with the exact same request. diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamUserCallableTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamUserCallableTest.java index 043d6ff3dd..84f9765ea6 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamUserCallableTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/changestream/ReadChangeStreamUserCallableTest.java @@ -21,10 +21,10 @@ import com.google.cloud.bigtable.data.v2.models.ReadChangeStreamQuery; import com.google.cloud.bigtable.gaxx.testing.FakeStreamingApi.ServerStreamingStashCallable; import com.google.common.truth.Truth; -import java.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.threeten.bp.Duration; import org.threeten.bp.Instant; @RunWith(JUnit4.class) diff --git a/google-cloud-bigtable/src/test/resources/changestream.json b/google-cloud-bigtable/src/test/resources/changestream.json index 9d9e2d46cc..661bf1b4cb 100644 --- a/google-cloud-bigtable/src/test/resources/changestream.json +++ b/google-cloud-bigtable/src/test/resources/changestream.json @@ -61,11 +61,25 @@ "partition": { "row_range": { "start_key_closed": "0000000000000001", - "end_key_open": "0000000000000002" + "end_key_open": "0000000000000003" } }, "token": "close-stream-token-2" } + ], + "new_partitions": [ + { + "row_range": { + "start_key_closed": "", + "end_key_open": "0000000000000002" + } + }, + { + "row_range": { + "start_key_closed": "0000000000000002", + "end_key_open": "0000000000000003" + } + } ] } } @@ -92,11 +106,25 @@ "partition": { "row_range": { "start_key_closed": "0000000000000001", - "end_key_open": "0000000000000002" + "end_key_open": "0000000000000003" } }, "token": "close-stream-token-2" } + ], + "new_partitions": [ + { + "row_range": { + "start_key_closed": "", + "end_key_open": "0000000000000002" + } + }, + { + "row_range": { + "start_key_closed": "0000000000000002", + "end_key_open": "0000000000000003" + } + } ] } }, @@ -137,6 +165,14 @@ }, "token": "close-stream-token-1" } + ], + "new_partitions": [ + { + "row_range": { + "start_key_closed": "", + "end_key_open": "0000000000000002" + } + } ] } } @@ -176,6 +212,14 @@ }, "token": "close-stream-token-1" } + ], + "new_partitions": [ + { + "row_range": { + "start_key_closed": "", + "end_key_open": "0000000000000002" + } + } ] } }, @@ -1280,11 +1324,25 @@ "partition": { "row_range": { "start_key_closed": "0000000000000001", - "end_key_open": "0000000000000002" + "end_key_open": "0000000000000003" } }, "token": "close-stream-token-2" } + ], + "new_partitions": [ + { + "row_range": { + "start_key_closed": "", + "end_key_open": "0000000000000002" + } + }, + { + "row_range": { + "start_key_closed": "0000000000000002", + "end_key_open": "0000000000000003" + } + } ] } } @@ -1363,11 +1421,25 @@ "partition": { "row_range": { "start_key_closed": "0000000000000001", - "end_key_open": "0000000000000002" + "end_key_open": "0000000000000003" } }, "token": "close-stream-token-2" } + ], + "new_partitions": [ + { + "row_range": { + "start_key_closed": "", + "end_key_open": "0000000000000002" + } + }, + { + "row_range": { + "start_key_closed": "0000000000000002", + "end_key_open": "0000000000000003" + } + } ] } }, diff --git a/grpc-google-cloud-bigtable-admin-v2/pom.xml b/grpc-google-cloud-bigtable-admin-v2/pom.xml index 2fadb56493..d8a0d7ce5e 100644 --- a/grpc-google-cloud-bigtable-admin-v2/pom.xml +++ b/grpc-google-cloud-bigtable-admin-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-bigtable-admin-v2 - 2.19.2 + 2.20.3 grpc-google-cloud-bigtable-admin-v2 GRPC library for grpc-google-cloud-bigtable-admin-v2 com.google.cloud google-cloud-bigtable-parent - 2.19.2 + 2.20.3 @@ -18,14 +18,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 2.19.2 + 2.20.3 pom import com.google.cloud google-cloud-bigtable-bom - 2.19.2 + 2.20.3 pom import @@ -74,7 +74,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.1 + 3.5.0 protected true diff --git a/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableInstanceAdminGrpc.java b/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableInstanceAdminGrpc.java index 8bc483256f..0a93eb51a4 100644 --- a/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableInstanceAdminGrpc.java +++ b/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableInstanceAdminGrpc.java @@ -1019,7 +1019,7 @@ public BigtableInstanceAdminFutureStub newStub( * tables' metadata or data stored in those tables. * */ - public abstract static class BigtableInstanceAdminImplBase implements io.grpc.BindableService { + public interface AsyncService { /** * @@ -1033,7 +1033,7 @@ public abstract static class BigtableInstanceAdminImplBase implements io.grpc.Bi * enabled. * */ - public void createInstance( + default void createInstance( com.google.bigtable.admin.v2.CreateInstanceRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1047,7 +1047,7 @@ public void createInstance( * Gets information about an instance. * */ - public void getInstance( + default void getInstance( com.google.bigtable.admin.v2.GetInstanceRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1061,7 +1061,7 @@ public void getInstance( * Lists information about instances in a project. * */ - public void listInstances( + default void listInstances( com.google.bigtable.admin.v2.ListInstancesRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1078,7 +1078,7 @@ public void listInstances( * labels, use PartialUpdateInstance. * */ - public void updateInstance( + default void updateInstance( com.google.bigtable.admin.v2.Instance request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1093,7 +1093,7 @@ public void updateInstance( * fields of an Instance and is the preferred way to update an Instance. * */ - public void partialUpdateInstance( + default void partialUpdateInstance( com.google.bigtable.admin.v2.PartialUpdateInstanceRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1107,7 +1107,7 @@ public void partialUpdateInstance( * Delete an instance from a project. * */ - public void deleteInstance( + default void deleteInstance( com.google.bigtable.admin.v2.DeleteInstanceRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1126,7 +1126,7 @@ public void deleteInstance( * enabled. * */ - public void createCluster( + default void createCluster( com.google.bigtable.admin.v2.CreateClusterRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1140,7 +1140,7 @@ public void createCluster( * Gets information about a cluster. * */ - public void getCluster( + default void getCluster( com.google.bigtable.admin.v2.GetClusterRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetClusterMethod(), responseObserver); @@ -1153,7 +1153,7 @@ public void getCluster( * Lists information about clusters in an instance. * */ - public void listClusters( + default void listClusters( com.google.bigtable.admin.v2.ListClustersRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1171,7 +1171,7 @@ public void listClusters( * must use PartialUpdateCluster. * */ - public void updateCluster( + default void updateCluster( com.google.bigtable.admin.v2.Cluster request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1194,7 +1194,7 @@ public void updateCluster( * and explicitly set a serve_node count via the update_mask. * */ - public void partialUpdateCluster( + default void partialUpdateCluster( com.google.bigtable.admin.v2.PartialUpdateClusterRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1208,7 +1208,7 @@ public void partialUpdateCluster( * Deletes a cluster from an instance. * */ - public void deleteCluster( + default void deleteCluster( com.google.bigtable.admin.v2.DeleteClusterRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1222,7 +1222,7 @@ public void deleteCluster( * Creates an app profile within an instance. * */ - public void createAppProfile( + default void createAppProfile( com.google.bigtable.admin.v2.CreateAppProfileRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1236,7 +1236,7 @@ public void createAppProfile( * Gets information about an app profile. * */ - public void getAppProfile( + default void getAppProfile( com.google.bigtable.admin.v2.GetAppProfileRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1250,7 +1250,7 @@ public void getAppProfile( * Lists information about app profiles in an instance. * */ - public void listAppProfiles( + default void listAppProfiles( com.google.bigtable.admin.v2.ListAppProfilesRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1265,7 +1265,7 @@ public void listAppProfiles( * Updates an app profile within an instance. * */ - public void updateAppProfile( + default void updateAppProfile( com.google.bigtable.admin.v2.UpdateAppProfileRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1279,7 +1279,7 @@ public void updateAppProfile( * Deletes an app profile from an instance. * */ - public void deleteAppProfile( + default void deleteAppProfile( com.google.bigtable.admin.v2.DeleteAppProfileRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1294,7 +1294,7 @@ public void deleteAppProfile( * policy if an instance exists but does not have a policy set. * */ - public void getIamPolicy( + default void getIamPolicy( com.google.iam.v1.GetIamPolicyRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1309,7 +1309,7 @@ public void getIamPolicy( * existing policy. * */ - public void setIamPolicy( + default void setIamPolicy( com.google.iam.v1.SetIamPolicyRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1323,7 +1323,7 @@ public void setIamPolicy( * Returns permissions that the caller has on the specified instance resource. * */ - public void testIamPermissions( + default void testIamPermissions( com.google.iam.v1.TestIamPermissionsRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1339,154 +1339,35 @@ public void testIamPermissions( * tablets are ordered based on CPU usage. * */ - public void listHotTablets( + default void listHotTablets( com.google.bigtable.admin.v2.ListHotTabletsRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( getListHotTabletsMethod(), responseObserver); } + } + + /** + * Base class for the server implementation of the service BigtableInstanceAdmin. + * + *
+   * Service for creating, configuring, and deleting Cloud Bigtable Instances and
+   * Clusters. Provides access to the Instance and Cluster schemas only, not the
+   * tables' metadata or data stored in those tables.
+   * 
+ */ + public abstract static class BigtableInstanceAdminImplBase + implements io.grpc.BindableService, AsyncService { @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { - return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) - .addMethod( - getCreateInstanceMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.CreateInstanceRequest, - com.google.longrunning.Operation>(this, METHODID_CREATE_INSTANCE))) - .addMethod( - getGetInstanceMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.GetInstanceRequest, - com.google.bigtable.admin.v2.Instance>(this, METHODID_GET_INSTANCE))) - .addMethod( - getListInstancesMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ListInstancesRequest, - com.google.bigtable.admin.v2.ListInstancesResponse>( - this, METHODID_LIST_INSTANCES))) - .addMethod( - getUpdateInstanceMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.Instance, com.google.bigtable.admin.v2.Instance>( - this, METHODID_UPDATE_INSTANCE))) - .addMethod( - getPartialUpdateInstanceMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.PartialUpdateInstanceRequest, - com.google.longrunning.Operation>(this, METHODID_PARTIAL_UPDATE_INSTANCE))) - .addMethod( - getDeleteInstanceMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.DeleteInstanceRequest, - com.google.protobuf.Empty>(this, METHODID_DELETE_INSTANCE))) - .addMethod( - getCreateClusterMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.CreateClusterRequest, - com.google.longrunning.Operation>(this, METHODID_CREATE_CLUSTER))) - .addMethod( - getGetClusterMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.GetClusterRequest, - com.google.bigtable.admin.v2.Cluster>(this, METHODID_GET_CLUSTER))) - .addMethod( - getListClustersMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ListClustersRequest, - com.google.bigtable.admin.v2.ListClustersResponse>( - this, METHODID_LIST_CLUSTERS))) - .addMethod( - getUpdateClusterMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.Cluster, com.google.longrunning.Operation>( - this, METHODID_UPDATE_CLUSTER))) - .addMethod( - getPartialUpdateClusterMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.PartialUpdateClusterRequest, - com.google.longrunning.Operation>(this, METHODID_PARTIAL_UPDATE_CLUSTER))) - .addMethod( - getDeleteClusterMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.DeleteClusterRequest, com.google.protobuf.Empty>( - this, METHODID_DELETE_CLUSTER))) - .addMethod( - getCreateAppProfileMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.CreateAppProfileRequest, - com.google.bigtable.admin.v2.AppProfile>(this, METHODID_CREATE_APP_PROFILE))) - .addMethod( - getGetAppProfileMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.GetAppProfileRequest, - com.google.bigtable.admin.v2.AppProfile>(this, METHODID_GET_APP_PROFILE))) - .addMethod( - getListAppProfilesMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ListAppProfilesRequest, - com.google.bigtable.admin.v2.ListAppProfilesResponse>( - this, METHODID_LIST_APP_PROFILES))) - .addMethod( - getUpdateAppProfileMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.UpdateAppProfileRequest, - com.google.longrunning.Operation>(this, METHODID_UPDATE_APP_PROFILE))) - .addMethod( - getDeleteAppProfileMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.DeleteAppProfileRequest, - com.google.protobuf.Empty>(this, METHODID_DELETE_APP_PROFILE))) - .addMethod( - getGetIamPolicyMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.iam.v1.GetIamPolicyRequest, com.google.iam.v1.Policy>( - this, METHODID_GET_IAM_POLICY))) - .addMethod( - getSetIamPolicyMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.iam.v1.SetIamPolicyRequest, com.google.iam.v1.Policy>( - this, METHODID_SET_IAM_POLICY))) - .addMethod( - getTestIamPermissionsMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.iam.v1.TestIamPermissionsRequest, - com.google.iam.v1.TestIamPermissionsResponse>( - this, METHODID_TEST_IAM_PERMISSIONS))) - .addMethod( - getListHotTabletsMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ListHotTabletsRequest, - com.google.bigtable.admin.v2.ListHotTabletsResponse>( - this, METHODID_LIST_HOT_TABLETS))) - .build(); + return BigtableInstanceAdminGrpc.bindService(this); } } /** - * + * A stub to allow clients to do asynchronous rpc calls to service BigtableInstanceAdmin. * *
    * Service for creating, configuring, and deleting Cloud Bigtable Instances and
@@ -1875,7 +1756,7 @@ public void listHotTablets(
   }
 
   /**
-   *
+   * A stub to allow clients to do synchronous rpc calls to service BigtableInstanceAdmin.
    *
    * 
    * Service for creating, configuring, and deleting Cloud Bigtable Instances and
@@ -2197,7 +2078,8 @@ public com.google.bigtable.admin.v2.ListHotTabletsResponse listHotTablets(
   }
 
   /**
-   *
+   * A stub to allow clients to do ListenableFuture-style rpc calls to service
+   * BigtableInstanceAdmin.
    *
    * 
    * Service for creating, configuring, and deleting Cloud Bigtable Instances and
@@ -2554,10 +2436,10 @@ private static final class MethodHandlers
           io.grpc.stub.ServerCalls.ServerStreamingMethod,
           io.grpc.stub.ServerCalls.ClientStreamingMethod,
           io.grpc.stub.ServerCalls.BidiStreamingMethod {
-    private final BigtableInstanceAdminImplBase serviceImpl;
+    private final AsyncService serviceImpl;
     private final int methodId;
 
-    MethodHandlers(BigtableInstanceAdminImplBase serviceImpl, int methodId) {
+    MethodHandlers(AsyncService serviceImpl, int methodId) {
       this.serviceImpl = serviceImpl;
       this.methodId = methodId;
     }
@@ -2696,6 +2578,140 @@ public io.grpc.stub.StreamObserver invoke(
     }
   }
 
+  public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
+    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+        .addMethod(
+            getCreateInstanceMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.CreateInstanceRequest,
+                    com.google.longrunning.Operation>(service, METHODID_CREATE_INSTANCE)))
+        .addMethod(
+            getGetInstanceMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.GetInstanceRequest,
+                    com.google.bigtable.admin.v2.Instance>(service, METHODID_GET_INSTANCE)))
+        .addMethod(
+            getListInstancesMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ListInstancesRequest,
+                    com.google.bigtable.admin.v2.ListInstancesResponse>(
+                    service, METHODID_LIST_INSTANCES)))
+        .addMethod(
+            getUpdateInstanceMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.Instance, com.google.bigtable.admin.v2.Instance>(
+                    service, METHODID_UPDATE_INSTANCE)))
+        .addMethod(
+            getPartialUpdateInstanceMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.PartialUpdateInstanceRequest,
+                    com.google.longrunning.Operation>(service, METHODID_PARTIAL_UPDATE_INSTANCE)))
+        .addMethod(
+            getDeleteInstanceMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.DeleteInstanceRequest, com.google.protobuf.Empty>(
+                    service, METHODID_DELETE_INSTANCE)))
+        .addMethod(
+            getCreateClusterMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.CreateClusterRequest,
+                    com.google.longrunning.Operation>(service, METHODID_CREATE_CLUSTER)))
+        .addMethod(
+            getGetClusterMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.GetClusterRequest,
+                    com.google.bigtable.admin.v2.Cluster>(service, METHODID_GET_CLUSTER)))
+        .addMethod(
+            getListClustersMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ListClustersRequest,
+                    com.google.bigtable.admin.v2.ListClustersResponse>(
+                    service, METHODID_LIST_CLUSTERS)))
+        .addMethod(
+            getUpdateClusterMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.Cluster, com.google.longrunning.Operation>(
+                    service, METHODID_UPDATE_CLUSTER)))
+        .addMethod(
+            getPartialUpdateClusterMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.PartialUpdateClusterRequest,
+                    com.google.longrunning.Operation>(service, METHODID_PARTIAL_UPDATE_CLUSTER)))
+        .addMethod(
+            getDeleteClusterMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.DeleteClusterRequest, com.google.protobuf.Empty>(
+                    service, METHODID_DELETE_CLUSTER)))
+        .addMethod(
+            getCreateAppProfileMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.CreateAppProfileRequest,
+                    com.google.bigtable.admin.v2.AppProfile>(service, METHODID_CREATE_APP_PROFILE)))
+        .addMethod(
+            getGetAppProfileMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.GetAppProfileRequest,
+                    com.google.bigtable.admin.v2.AppProfile>(service, METHODID_GET_APP_PROFILE)))
+        .addMethod(
+            getListAppProfilesMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ListAppProfilesRequest,
+                    com.google.bigtable.admin.v2.ListAppProfilesResponse>(
+                    service, METHODID_LIST_APP_PROFILES)))
+        .addMethod(
+            getUpdateAppProfileMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.UpdateAppProfileRequest,
+                    com.google.longrunning.Operation>(service, METHODID_UPDATE_APP_PROFILE)))
+        .addMethod(
+            getDeleteAppProfileMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.DeleteAppProfileRequest,
+                    com.google.protobuf.Empty>(service, METHODID_DELETE_APP_PROFILE)))
+        .addMethod(
+            getGetIamPolicyMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers(
+                    service, METHODID_GET_IAM_POLICY)))
+        .addMethod(
+            getSetIamPolicyMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers(
+                    service, METHODID_SET_IAM_POLICY)))
+        .addMethod(
+            getTestIamPermissionsMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.iam.v1.TestIamPermissionsRequest,
+                    com.google.iam.v1.TestIamPermissionsResponse>(
+                    service, METHODID_TEST_IAM_PERMISSIONS)))
+        .addMethod(
+            getListHotTabletsMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ListHotTabletsRequest,
+                    com.google.bigtable.admin.v2.ListHotTabletsResponse>(
+                    service, METHODID_LIST_HOT_TABLETS)))
+        .build();
+  }
+
   private abstract static class BigtableInstanceAdminBaseDescriptorSupplier
       implements io.grpc.protobuf.ProtoFileDescriptorSupplier,
           io.grpc.protobuf.ProtoServiceDescriptorSupplier {
diff --git a/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableTableAdminGrpc.java b/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableTableAdminGrpc.java
index b4d101214c..35aefa6d88 100644
--- a/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableTableAdminGrpc.java
+++ b/grpc-google-cloud-bigtable-admin-v2/src/main/java/com/google/bigtable/admin/v2/BigtableTableAdminGrpc.java
@@ -1141,7 +1141,7 @@ public BigtableTableAdminFutureStub newStub(
    * the tables.
    * 
*/ - public abstract static class BigtableTableAdminImplBase implements io.grpc.BindableService { + public interface AsyncService { /** * @@ -1152,7 +1152,7 @@ public abstract static class BigtableTableAdminImplBase implements io.grpc.Binda * specified in the request. *
*/ - public void createTable( + default void createTable( com.google.bigtable.admin.v2.CreateTableRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1172,7 +1172,7 @@ public void createTable( * policy. *
*/ - public void createTableFromSnapshot( + default void createTableFromSnapshot( com.google.bigtable.admin.v2.CreateTableFromSnapshotRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1186,7 +1186,7 @@ public void createTableFromSnapshot( * Lists all tables served from a specified instance. * */ - public void listTables( + default void listTables( com.google.bigtable.admin.v2.ListTablesRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1200,7 +1200,7 @@ public void listTables( * Gets metadata information about the specified table. * */ - public void getTable( + default void getTable( com.google.bigtable.admin.v2.GetTableRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetTableMethod(), responseObserver); @@ -1213,7 +1213,7 @@ public void getTable( * Updates a specified table. * */ - public void updateTable( + default void updateTable( com.google.bigtable.admin.v2.UpdateTableRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1227,7 +1227,7 @@ public void updateTable( * Permanently deletes a specified table and all of its data. * */ - public void deleteTable( + default void deleteTable( com.google.bigtable.admin.v2.DeleteTableRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1241,7 +1241,7 @@ public void deleteTable( * Restores a specified table which was accidentally deleted. * */ - public void undeleteTable( + default void undeleteTable( com.google.bigtable.admin.v2.UndeleteTableRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1258,7 +1258,7 @@ public void undeleteTable( * where only some modifications have taken effect. * */ - public void modifyColumnFamilies( + default void modifyColumnFamilies( com.google.bigtable.admin.v2.ModifyColumnFamiliesRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1274,7 +1274,7 @@ public void modifyColumnFamilies( * particular prefix. * */ - public void dropRowRange( + default void dropRowRange( com.google.bigtable.admin.v2.DropRowRangeRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1291,7 +1291,7 @@ public void dropRowRange( * for 90 days. * */ - public void generateConsistencyToken( + default void generateConsistencyToken( com.google.bigtable.admin.v2.GenerateConsistencyTokenRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1308,7 +1308,7 @@ public void generateConsistencyToken( * and the check request. * */ - public void checkConsistency( + default void checkConsistency( com.google.bigtable.admin.v2.CheckConsistencyRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1329,7 +1329,7 @@ public void checkConsistency( * policy. * */ - public void snapshotTable( + default void snapshotTable( com.google.bigtable.admin.v2.SnapshotTableRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1348,7 +1348,7 @@ public void snapshotTable( * policy. * */ - public void getSnapshot( + default void getSnapshot( com.google.bigtable.admin.v2.GetSnapshotRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1367,7 +1367,7 @@ public void getSnapshot( * policy. * */ - public void listSnapshots( + default void listSnapshots( com.google.bigtable.admin.v2.ListSnapshotsRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1387,7 +1387,7 @@ public void listSnapshots( * policy. * */ - public void deleteSnapshot( + default void deleteSnapshot( com.google.bigtable.admin.v2.DeleteSnapshotRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1408,7 +1408,7 @@ public void deleteSnapshot( * creation and delete the backup. * */ - public void createBackup( + default void createBackup( com.google.bigtable.admin.v2.CreateBackupRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1422,7 +1422,7 @@ public void createBackup( * Gets metadata on a pending or completed Cloud Bigtable Backup. * */ - public void getBackup( + default void getBackup( com.google.bigtable.admin.v2.GetBackupRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetBackupMethod(), responseObserver); @@ -1435,7 +1435,7 @@ public void getBackup( * Updates a pending or completed Cloud Bigtable Backup. * */ - public void updateBackup( + default void updateBackup( com.google.bigtable.admin.v2.UpdateBackupRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1449,7 +1449,7 @@ public void updateBackup( * Deletes a pending or completed Cloud Bigtable backup. * */ - public void deleteBackup( + default void deleteBackup( com.google.bigtable.admin.v2.DeleteBackupRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1464,7 +1464,7 @@ public void deleteBackup( * backups. * */ - public void listBackups( + default void listBackups( com.google.bigtable.admin.v2.ListBackupsRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -1486,7 +1486,7 @@ public void listBackups( * [Table][google.bigtable.admin.v2.Table], if successful. * */ - public void restoreTable( + default void restoreTable( com.google.bigtable.admin.v2.RestoreTableRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1502,7 +1502,7 @@ public void restoreTable( * set. * */ - public void getIamPolicy( + default void getIamPolicy( com.google.iam.v1.GetIamPolicyRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1517,7 +1517,7 @@ public void getIamPolicy( * Replaces any existing policy. * */ - public void setIamPolicy( + default void setIamPolicy( com.google.iam.v1.SetIamPolicyRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -1531,172 +1531,35 @@ public void setIamPolicy( * Returns permissions that the caller has on the specified Table or Backup resource. * */ - public void testIamPermissions( + default void testIamPermissions( com.google.iam.v1.TestIamPermissionsRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( getTestIamPermissionsMethod(), responseObserver); } + } + + /** + * Base class for the server implementation of the service BigtableTableAdmin. + * + *
+   * Service for creating, configuring, and deleting Cloud Bigtable tables.
+   * Provides access to the table schemas only, not the data stored within
+   * the tables.
+   * 
+ */ + public abstract static class BigtableTableAdminImplBase + implements io.grpc.BindableService, AsyncService { @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { - return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) - .addMethod( - getCreateTableMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.CreateTableRequest, - com.google.bigtable.admin.v2.Table>(this, METHODID_CREATE_TABLE))) - .addMethod( - getCreateTableFromSnapshotMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.CreateTableFromSnapshotRequest, - com.google.longrunning.Operation>(this, METHODID_CREATE_TABLE_FROM_SNAPSHOT))) - .addMethod( - getListTablesMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ListTablesRequest, - com.google.bigtable.admin.v2.ListTablesResponse>(this, METHODID_LIST_TABLES))) - .addMethod( - getGetTableMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.GetTableRequest, - com.google.bigtable.admin.v2.Table>(this, METHODID_GET_TABLE))) - .addMethod( - getUpdateTableMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.UpdateTableRequest, - com.google.longrunning.Operation>(this, METHODID_UPDATE_TABLE))) - .addMethod( - getDeleteTableMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.DeleteTableRequest, com.google.protobuf.Empty>( - this, METHODID_DELETE_TABLE))) - .addMethod( - getUndeleteTableMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.UndeleteTableRequest, - com.google.longrunning.Operation>(this, METHODID_UNDELETE_TABLE))) - .addMethod( - getModifyColumnFamiliesMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ModifyColumnFamiliesRequest, - com.google.bigtable.admin.v2.Table>(this, METHODID_MODIFY_COLUMN_FAMILIES))) - .addMethod( - getDropRowRangeMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.DropRowRangeRequest, com.google.protobuf.Empty>( - this, METHODID_DROP_ROW_RANGE))) - .addMethod( - getGenerateConsistencyTokenMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.GenerateConsistencyTokenRequest, - com.google.bigtable.admin.v2.GenerateConsistencyTokenResponse>( - this, METHODID_GENERATE_CONSISTENCY_TOKEN))) - .addMethod( - getCheckConsistencyMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.CheckConsistencyRequest, - com.google.bigtable.admin.v2.CheckConsistencyResponse>( - this, METHODID_CHECK_CONSISTENCY))) - .addMethod( - getSnapshotTableMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.SnapshotTableRequest, - com.google.longrunning.Operation>(this, METHODID_SNAPSHOT_TABLE))) - .addMethod( - getGetSnapshotMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.GetSnapshotRequest, - com.google.bigtable.admin.v2.Snapshot>(this, METHODID_GET_SNAPSHOT))) - .addMethod( - getListSnapshotsMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ListSnapshotsRequest, - com.google.bigtable.admin.v2.ListSnapshotsResponse>( - this, METHODID_LIST_SNAPSHOTS))) - .addMethod( - getDeleteSnapshotMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.DeleteSnapshotRequest, - com.google.protobuf.Empty>(this, METHODID_DELETE_SNAPSHOT))) - .addMethod( - getCreateBackupMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.CreateBackupRequest, - com.google.longrunning.Operation>(this, METHODID_CREATE_BACKUP))) - .addMethod( - getGetBackupMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.GetBackupRequest, - com.google.bigtable.admin.v2.Backup>(this, METHODID_GET_BACKUP))) - .addMethod( - getUpdateBackupMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.UpdateBackupRequest, - com.google.bigtable.admin.v2.Backup>(this, METHODID_UPDATE_BACKUP))) - .addMethod( - getDeleteBackupMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.DeleteBackupRequest, com.google.protobuf.Empty>( - this, METHODID_DELETE_BACKUP))) - .addMethod( - getListBackupsMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.ListBackupsRequest, - com.google.bigtable.admin.v2.ListBackupsResponse>( - this, METHODID_LIST_BACKUPS))) - .addMethod( - getRestoreTableMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.admin.v2.RestoreTableRequest, - com.google.longrunning.Operation>(this, METHODID_RESTORE_TABLE))) - .addMethod( - getGetIamPolicyMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.iam.v1.GetIamPolicyRequest, com.google.iam.v1.Policy>( - this, METHODID_GET_IAM_POLICY))) - .addMethod( - getSetIamPolicyMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.iam.v1.SetIamPolicyRequest, com.google.iam.v1.Policy>( - this, METHODID_SET_IAM_POLICY))) - .addMethod( - getTestIamPermissionsMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.iam.v1.TestIamPermissionsRequest, - com.google.iam.v1.TestIamPermissionsResponse>( - this, METHODID_TEST_IAM_PERMISSIONS))) - .build(); + return BigtableTableAdminGrpc.bindService(this); } } /** - * + * A stub to allow clients to do asynchronous rpc calls to service BigtableTableAdmin. * *
    * Service for creating, configuring, and deleting Cloud Bigtable tables.
@@ -2159,7 +2022,7 @@ public void testIamPermissions(
   }
 
   /**
-   *
+   * A stub to allow clients to do synchronous rpc calls to service BigtableTableAdmin.
    *
    * 
    * Service for creating, configuring, and deleting Cloud Bigtable tables.
@@ -2549,7 +2412,7 @@ public com.google.iam.v1.TestIamPermissionsResponse testIamPermissions(
   }
 
   /**
-   *
+   * A stub to allow clients to do ListenableFuture-style rpc calls to service BigtableTableAdmin.
    *
    * 
    * Service for creating, configuring, and deleting Cloud Bigtable tables.
@@ -2977,10 +2840,10 @@ private static final class MethodHandlers
           io.grpc.stub.ServerCalls.ServerStreamingMethod,
           io.grpc.stub.ServerCalls.ClientStreamingMethod,
           io.grpc.stub.ServerCalls.BidiStreamingMethod {
-    private final BigtableTableAdminImplBase serviceImpl;
+    private final AsyncService serviceImpl;
     private final int methodId;
 
-    MethodHandlers(BigtableTableAdminImplBase serviceImpl, int methodId) {
+    MethodHandlers(AsyncService serviceImpl, int methodId) {
       this.serviceImpl = serviceImpl;
       this.methodId = methodId;
     }
@@ -3133,6 +2996,160 @@ public io.grpc.stub.StreamObserver invoke(
     }
   }
 
+  public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
+    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+        .addMethod(
+            getCreateTableMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.CreateTableRequest,
+                    com.google.bigtable.admin.v2.Table>(service, METHODID_CREATE_TABLE)))
+        .addMethod(
+            getCreateTableFromSnapshotMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.CreateTableFromSnapshotRequest,
+                    com.google.longrunning.Operation>(
+                    service, METHODID_CREATE_TABLE_FROM_SNAPSHOT)))
+        .addMethod(
+            getListTablesMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ListTablesRequest,
+                    com.google.bigtable.admin.v2.ListTablesResponse>(
+                    service, METHODID_LIST_TABLES)))
+        .addMethod(
+            getGetTableMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.GetTableRequest,
+                    com.google.bigtable.admin.v2.Table>(service, METHODID_GET_TABLE)))
+        .addMethod(
+            getUpdateTableMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.UpdateTableRequest,
+                    com.google.longrunning.Operation>(service, METHODID_UPDATE_TABLE)))
+        .addMethod(
+            getDeleteTableMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.DeleteTableRequest, com.google.protobuf.Empty>(
+                    service, METHODID_DELETE_TABLE)))
+        .addMethod(
+            getUndeleteTableMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.UndeleteTableRequest,
+                    com.google.longrunning.Operation>(service, METHODID_UNDELETE_TABLE)))
+        .addMethod(
+            getModifyColumnFamiliesMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ModifyColumnFamiliesRequest,
+                    com.google.bigtable.admin.v2.Table>(service, METHODID_MODIFY_COLUMN_FAMILIES)))
+        .addMethod(
+            getDropRowRangeMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.DropRowRangeRequest, com.google.protobuf.Empty>(
+                    service, METHODID_DROP_ROW_RANGE)))
+        .addMethod(
+            getGenerateConsistencyTokenMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.GenerateConsistencyTokenRequest,
+                    com.google.bigtable.admin.v2.GenerateConsistencyTokenResponse>(
+                    service, METHODID_GENERATE_CONSISTENCY_TOKEN)))
+        .addMethod(
+            getCheckConsistencyMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.CheckConsistencyRequest,
+                    com.google.bigtable.admin.v2.CheckConsistencyResponse>(
+                    service, METHODID_CHECK_CONSISTENCY)))
+        .addMethod(
+            getSnapshotTableMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.SnapshotTableRequest,
+                    com.google.longrunning.Operation>(service, METHODID_SNAPSHOT_TABLE)))
+        .addMethod(
+            getGetSnapshotMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.GetSnapshotRequest,
+                    com.google.bigtable.admin.v2.Snapshot>(service, METHODID_GET_SNAPSHOT)))
+        .addMethod(
+            getListSnapshotsMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ListSnapshotsRequest,
+                    com.google.bigtable.admin.v2.ListSnapshotsResponse>(
+                    service, METHODID_LIST_SNAPSHOTS)))
+        .addMethod(
+            getDeleteSnapshotMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.DeleteSnapshotRequest, com.google.protobuf.Empty>(
+                    service, METHODID_DELETE_SNAPSHOT)))
+        .addMethod(
+            getCreateBackupMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.CreateBackupRequest,
+                    com.google.longrunning.Operation>(service, METHODID_CREATE_BACKUP)))
+        .addMethod(
+            getGetBackupMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.GetBackupRequest,
+                    com.google.bigtable.admin.v2.Backup>(service, METHODID_GET_BACKUP)))
+        .addMethod(
+            getUpdateBackupMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.UpdateBackupRequest,
+                    com.google.bigtable.admin.v2.Backup>(service, METHODID_UPDATE_BACKUP)))
+        .addMethod(
+            getDeleteBackupMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.DeleteBackupRequest, com.google.protobuf.Empty>(
+                    service, METHODID_DELETE_BACKUP)))
+        .addMethod(
+            getListBackupsMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.ListBackupsRequest,
+                    com.google.bigtable.admin.v2.ListBackupsResponse>(
+                    service, METHODID_LIST_BACKUPS)))
+        .addMethod(
+            getRestoreTableMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.admin.v2.RestoreTableRequest,
+                    com.google.longrunning.Operation>(service, METHODID_RESTORE_TABLE)))
+        .addMethod(
+            getGetIamPolicyMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers(
+                    service, METHODID_GET_IAM_POLICY)))
+        .addMethod(
+            getSetIamPolicyMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers(
+                    service, METHODID_SET_IAM_POLICY)))
+        .addMethod(
+            getTestIamPermissionsMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.iam.v1.TestIamPermissionsRequest,
+                    com.google.iam.v1.TestIamPermissionsResponse>(
+                    service, METHODID_TEST_IAM_PERMISSIONS)))
+        .build();
+  }
+
   private abstract static class BigtableTableAdminBaseDescriptorSupplier
       implements io.grpc.protobuf.ProtoFileDescriptorSupplier,
           io.grpc.protobuf.ProtoServiceDescriptorSupplier {
diff --git a/grpc-google-cloud-bigtable-v2/pom.xml b/grpc-google-cloud-bigtable-v2/pom.xml
index 28cdba2c32..da21ded083 100644
--- a/grpc-google-cloud-bigtable-v2/pom.xml
+++ b/grpc-google-cloud-bigtable-v2/pom.xml
@@ -4,13 +4,13 @@
   4.0.0
   com.google.api.grpc
   grpc-google-cloud-bigtable-v2
-  2.19.2
+  2.20.3
   grpc-google-cloud-bigtable-v2
   GRPC library for grpc-google-cloud-bigtable-v2
   
     com.google.cloud
     google-cloud-bigtable-parent
-    2.19.2
+    2.20.3
   
 
   
@@ -18,14 +18,14 @@
       
         com.google.cloud
         google-cloud-bigtable-deps-bom
-        2.19.2
+        2.20.3
         pom
         import
       
       
         com.google.cloud
         google-cloud-bigtable-bom
-        2.19.2
+        2.20.3
         pom
         import
       
@@ -66,7 +66,7 @@
       
         org.apache.maven.plugins
         maven-javadoc-plugin
-        3.4.1
+        3.5.0
         
           protected
           true
diff --git a/grpc-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableGrpc.java b/grpc-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableGrpc.java
index 960bd47fe0..0b661a4358 100644
--- a/grpc-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableGrpc.java
+++ b/grpc-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableGrpc.java
@@ -479,7 +479,7 @@ public BigtableFutureStub newStub(
    * Service for reading from and writing to existing Bigtable tables.
    * 
*/ - public abstract static class BigtableImplBase implements io.grpc.BindableService { + public interface AsyncService { /** * @@ -492,7 +492,7 @@ public abstract static class BigtableImplBase implements io.grpc.BindableService * ReadRowsResponse documentation for details. *
*/ - public void readRows( + default void readRows( com.google.bigtable.v2.ReadRowsRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getReadRowsMethod(), responseObserver); @@ -508,7 +508,7 @@ public void readRows( * mapreduces. *
*/ - public void sampleRowKeys( + default void sampleRowKeys( com.google.bigtable.v2.SampleRowKeysRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -524,7 +524,7 @@ public void sampleRowKeys( * unchanged unless explicitly changed by `mutation`. * */ - public void mutateRow( + default void mutateRow( com.google.bigtable.v2.MutateRowRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getMutateRowMethod(), responseObserver); @@ -539,7 +539,7 @@ public void mutateRow( * atomically. * */ - public void mutateRows( + default void mutateRows( com.google.bigtable.v2.MutateRowsRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getMutateRowsMethod(), responseObserver); @@ -552,7 +552,7 @@ public void mutateRows( * Mutates a row atomically based on the output of a predicate Reader filter. * */ - public void checkAndMutateRow( + default void checkAndMutateRow( com.google.bigtable.v2.CheckAndMutateRowRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -568,7 +568,7 @@ public void checkAndMutateRow( * This call is not required but may be useful for connection keep-alive. * */ - public void pingAndWarm( + default void pingAndWarm( com.google.bigtable.v2.PingAndWarmRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( @@ -586,7 +586,7 @@ public void pingAndWarm( * time. The method returns the new contents of all modified cells. * */ - public void readModifyWriteRow( + default void readModifyWriteRow( com.google.bigtable.v2.ReadModifyWriteRowRequest request, io.grpc.stub.StreamObserver responseObserver) { @@ -604,7 +604,7 @@ public void readModifyWriteRow( * Partitions can be read with `ReadChangeStream`. * */ - public void generateInitialChangeStreamPartitions( + default void generateInitialChangeStreamPartitions( com.google.bigtable.v2.GenerateInitialChangeStreamPartitionsRequest request, io.grpc.stub.StreamObserver< com.google.bigtable.v2.GenerateInitialChangeStreamPartitionsResponse> @@ -623,82 +623,32 @@ public void generateInitialChangeStreamPartitions( * garbage collection. * */ - public void readChangeStream( + default void readChangeStream( com.google.bigtable.v2.ReadChangeStreamRequest request, io.grpc.stub.StreamObserver responseObserver) { io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall( getReadChangeStreamMethod(), responseObserver); } + } + + /** + * Base class for the server implementation of the service Bigtable. + * + *
+   * Service for reading from and writing to existing Bigtable tables.
+   * 
+ */ + public abstract static class BigtableImplBase implements io.grpc.BindableService, AsyncService { @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { - return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) - .addMethod( - getReadRowsMethod(), - io.grpc.stub.ServerCalls.asyncServerStreamingCall( - new MethodHandlers< - com.google.bigtable.v2.ReadRowsRequest, - com.google.bigtable.v2.ReadRowsResponse>(this, METHODID_READ_ROWS))) - .addMethod( - getSampleRowKeysMethod(), - io.grpc.stub.ServerCalls.asyncServerStreamingCall( - new MethodHandlers< - com.google.bigtable.v2.SampleRowKeysRequest, - com.google.bigtable.v2.SampleRowKeysResponse>( - this, METHODID_SAMPLE_ROW_KEYS))) - .addMethod( - getMutateRowMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.v2.MutateRowRequest, - com.google.bigtable.v2.MutateRowResponse>(this, METHODID_MUTATE_ROW))) - .addMethod( - getMutateRowsMethod(), - io.grpc.stub.ServerCalls.asyncServerStreamingCall( - new MethodHandlers< - com.google.bigtable.v2.MutateRowsRequest, - com.google.bigtable.v2.MutateRowsResponse>(this, METHODID_MUTATE_ROWS))) - .addMethod( - getCheckAndMutateRowMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.v2.CheckAndMutateRowRequest, - com.google.bigtable.v2.CheckAndMutateRowResponse>( - this, METHODID_CHECK_AND_MUTATE_ROW))) - .addMethod( - getPingAndWarmMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.v2.PingAndWarmRequest, - com.google.bigtable.v2.PingAndWarmResponse>(this, METHODID_PING_AND_WARM))) - .addMethod( - getReadModifyWriteRowMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - com.google.bigtable.v2.ReadModifyWriteRowRequest, - com.google.bigtable.v2.ReadModifyWriteRowResponse>( - this, METHODID_READ_MODIFY_WRITE_ROW))) - .addMethod( - getGenerateInitialChangeStreamPartitionsMethod(), - io.grpc.stub.ServerCalls.asyncServerStreamingCall( - new MethodHandlers< - com.google.bigtable.v2.GenerateInitialChangeStreamPartitionsRequest, - com.google.bigtable.v2.GenerateInitialChangeStreamPartitionsResponse>( - this, METHODID_GENERATE_INITIAL_CHANGE_STREAM_PARTITIONS))) - .addMethod( - getReadChangeStreamMethod(), - io.grpc.stub.ServerCalls.asyncServerStreamingCall( - new MethodHandlers< - com.google.bigtable.v2.ReadChangeStreamRequest, - com.google.bigtable.v2.ReadChangeStreamResponse>( - this, METHODID_READ_CHANGE_STREAM))) - .build(); + return BigtableGrpc.bindService(this); } } /** - * + * A stub to allow clients to do asynchronous rpc calls to service Bigtable. * *
    * Service for reading from and writing to existing Bigtable tables.
@@ -881,7 +831,7 @@ public void readChangeStream(
   }
 
   /**
-   *
+   * A stub to allow clients to do synchronous rpc calls to service Bigtable.
    *
    * 
    * Service for reading from and writing to existing Bigtable tables.
@@ -1042,7 +992,7 @@ public java.util.Iterator readC
   }
 
   /**
-   *
+   * A stub to allow clients to do ListenableFuture-style rpc calls to service Bigtable.
    *
    * 
    * Service for reading from and writing to existing Bigtable tables.
@@ -1137,10 +1087,10 @@ private static final class MethodHandlers
           io.grpc.stub.ServerCalls.ServerStreamingMethod,
           io.grpc.stub.ServerCalls.ClientStreamingMethod,
           io.grpc.stub.ServerCalls.BidiStreamingMethod {
-    private final BigtableImplBase serviceImpl;
+    private final AsyncService serviceImpl;
     private final int methodId;
 
-    MethodHandlers(BigtableImplBase serviceImpl, int methodId) {
+    MethodHandlers(AsyncService serviceImpl, int methodId) {
       this.serviceImpl = serviceImpl;
       this.methodId = methodId;
     }
@@ -1220,6 +1170,70 @@ public io.grpc.stub.StreamObserver invoke(
     }
   }
 
+  public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
+    return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+        .addMethod(
+            getReadRowsMethod(),
+            io.grpc.stub.ServerCalls.asyncServerStreamingCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.ReadRowsRequest,
+                    com.google.bigtable.v2.ReadRowsResponse>(service, METHODID_READ_ROWS)))
+        .addMethod(
+            getSampleRowKeysMethod(),
+            io.grpc.stub.ServerCalls.asyncServerStreamingCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.SampleRowKeysRequest,
+                    com.google.bigtable.v2.SampleRowKeysResponse>(
+                    service, METHODID_SAMPLE_ROW_KEYS)))
+        .addMethod(
+            getMutateRowMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.MutateRowRequest,
+                    com.google.bigtable.v2.MutateRowResponse>(service, METHODID_MUTATE_ROW)))
+        .addMethod(
+            getMutateRowsMethod(),
+            io.grpc.stub.ServerCalls.asyncServerStreamingCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.MutateRowsRequest,
+                    com.google.bigtable.v2.MutateRowsResponse>(service, METHODID_MUTATE_ROWS)))
+        .addMethod(
+            getCheckAndMutateRowMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.CheckAndMutateRowRequest,
+                    com.google.bigtable.v2.CheckAndMutateRowResponse>(
+                    service, METHODID_CHECK_AND_MUTATE_ROW)))
+        .addMethod(
+            getPingAndWarmMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.PingAndWarmRequest,
+                    com.google.bigtable.v2.PingAndWarmResponse>(service, METHODID_PING_AND_WARM)))
+        .addMethod(
+            getReadModifyWriteRowMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.ReadModifyWriteRowRequest,
+                    com.google.bigtable.v2.ReadModifyWriteRowResponse>(
+                    service, METHODID_READ_MODIFY_WRITE_ROW)))
+        .addMethod(
+            getGenerateInitialChangeStreamPartitionsMethod(),
+            io.grpc.stub.ServerCalls.asyncServerStreamingCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.GenerateInitialChangeStreamPartitionsRequest,
+                    com.google.bigtable.v2.GenerateInitialChangeStreamPartitionsResponse>(
+                    service, METHODID_GENERATE_INITIAL_CHANGE_STREAM_PARTITIONS)))
+        .addMethod(
+            getReadChangeStreamMethod(),
+            io.grpc.stub.ServerCalls.asyncServerStreamingCall(
+                new MethodHandlers<
+                    com.google.bigtable.v2.ReadChangeStreamRequest,
+                    com.google.bigtable.v2.ReadChangeStreamResponse>(
+                    service, METHODID_READ_CHANGE_STREAM)))
+        .build();
+  }
+
   private abstract static class BigtableBaseDescriptorSupplier
       implements io.grpc.protobuf.ProtoFileDescriptorSupplier,
           io.grpc.protobuf.ProtoServiceDescriptorSupplier {
diff --git a/owlbot.py b/owlbot.py
index 2daf394127..8b33b41998 100644
--- a/owlbot.py
+++ b/owlbot.py
@@ -109,4 +109,5 @@ def make_internal_only(sources):
     'codecov.yaml'
     # needed for extraFiles
     '.github/release-please.yml',
+    'renovate.json',
 ])
diff --git a/pom.xml b/pom.xml
index 6d1501a968..e07b065746 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 
     google-cloud-bigtable-parent
     pom
-    2.19.2
+    2.20.3
     Google Cloud Bigtable Parent
     https://github.com/googleapis/java-bigtable
     
@@ -153,33 +153,33 @@
             
                 com.google.api.grpc
                 proto-google-cloud-bigtable-v2
-                2.19.2
+                2.20.3
             
             
                 com.google.api.grpc
                 proto-google-cloud-bigtable-admin-v2
-                2.19.2
+                2.20.3
             
             
                 com.google.api.grpc
                 grpc-google-cloud-bigtable-v2
-                2.19.2
+                2.20.3
             
             
                 com.google.api.grpc
                 grpc-google-cloud-bigtable-admin-v2
-                2.19.2
+                2.20.3
             
             
                 com.google.cloud
                 google-cloud-bigtable
-                2.19.2
+                2.20.3
             
             
             
                 com.google.cloud
                 google-cloud-conformance-tests
-                0.3.4
+                0.3.5
             
             
                 com.google.truth
@@ -226,7 +226,7 @@
             
                 org.apache.maven.plugins
                 maven-javadoc-plugin
-                3.4.1
+                3.5.0
                 
                     
                         aggregate
@@ -317,7 +317,7 @@
                     
                         org.apache.maven.plugins
                         maven-javadoc-plugin
-                        3.4.1
+                        3.5.0
                         
                             
                             com.microsoft.doclet.DocFxDoclet
diff --git a/proto-google-cloud-bigtable-admin-v2/pom.xml b/proto-google-cloud-bigtable-admin-v2/pom.xml
index d0ab4c144f..9135aefe07 100644
--- a/proto-google-cloud-bigtable-admin-v2/pom.xml
+++ b/proto-google-cloud-bigtable-admin-v2/pom.xml
@@ -4,13 +4,13 @@
   4.0.0
   com.google.api.grpc
   proto-google-cloud-bigtable-admin-v2
-  2.19.2
+  2.20.3
   proto-google-cloud-bigtable-admin-v2
   PROTO library for proto-google-cloud-bigtable-admin-v2
   
     com.google.cloud
     google-cloud-bigtable-parent
-    2.19.2
+    2.20.3
   
 
   
@@ -18,14 +18,14 @@
       
         com.google.cloud
         google-cloud-bigtable-deps-bom
-        2.19.2
+        2.20.3
         pom
         import
       
       
         com.google.cloud
         google-cloud-bigtable-bom
-        2.19.2
+        2.20.3
         pom
         import
       
diff --git a/proto-google-cloud-bigtable-v2/pom.xml b/proto-google-cloud-bigtable-v2/pom.xml
index 2d6de218d9..0b54c3e05f 100644
--- a/proto-google-cloud-bigtable-v2/pom.xml
+++ b/proto-google-cloud-bigtable-v2/pom.xml
@@ -4,13 +4,13 @@
   4.0.0
   com.google.api.grpc
   proto-google-cloud-bigtable-v2
-  2.19.2
+  2.20.3
   proto-google-cloud-bigtable-v2
   PROTO library for proto-google-cloud-bigtable-v2
   
     com.google.cloud
     google-cloud-bigtable-parent
-    2.19.2
+    2.20.3
   
 
   
@@ -18,14 +18,14 @@
       
         com.google.cloud
         google-cloud-bigtable-deps-bom
-        2.19.2
+        2.20.3
         pom
         import
       
       
         com.google.cloud
         google-cloud-bigtable-bom
-        2.19.2
+        2.20.3
         pom
         import
       
diff --git a/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableProto.java b/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableProto.java
index ba23c35367..87ba2cbdd2 100644
--- a/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableProto.java
+++ b/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/BigtableProto.java
@@ -225,7 +225,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
           + "able.v2.StreamContinuationTokensH\000\022,\n\010en"
           + "d_time\030\005 \001(\0132\032.google.protobuf.Timestamp"
           + "\0225\n\022heartbeat_duration\030\007 \001(\0132\031.google.pr"
-          + "otobuf.DurationB\014\n\nstart_from\"\353\t\n\030ReadCh"
+          + "otobuf.DurationB\014\n\nstart_from\"\251\n\n\030ReadCh"
           + "angeStreamResponse\022N\n\013data_change\030\001 \001(\0132"
           + "7.google.bigtable.v2.ReadChangeStreamRes"
           + "ponse.DataChangeH\000\022K\n\theartbeat\030\002 \001(\01326."
@@ -253,99 +253,101 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
           + "\003\032\221\001\n\tHeartbeat\022G\n\022continuation_token\030\001 "
           + "\001(\0132+.google.bigtable.v2.StreamContinuat"
           + "ionToken\022;\n\027estimated_low_watermark\030\002 \001("
-          + "\0132\032.google.protobuf.Timestamp\032{\n\013CloseSt"
-          + "ream\022\"\n\006status\030\001 \001(\0132\022.google.rpc.Status"
-          + "\022H\n\023continuation_tokens\030\002 \003(\0132+.google.b"
-          + "igtable.v2.StreamContinuationTokenB\017\n\rst"
-          + "ream_record2\327\030\n\010Bigtable\022\233\002\n\010ReadRows\022#."
-          + "google.bigtable.v2.ReadRowsRequest\032$.goo"
-          + "gle.bigtable.v2.ReadRowsResponse\"\301\001\202\323\344\223\002"
-          + ">\"9/v2/{table_name=projects/*/instances/"
-          + "*/tables/*}:readRows:\001*\212\323\344\223\002N\022:\n\ntable_n"
-          + "ame\022,{table_name=projects/*/instances/*/"
-          + "tables/*}\022\020\n\016app_profile_id\332A\ntable_name"
-          + "\332A\031table_name,app_profile_id0\001\022\254\002\n\rSampl"
-          + "eRowKeys\022(.google.bigtable.v2.SampleRowK"
-          + "eysRequest\032).google.bigtable.v2.SampleRo"
-          + "wKeysResponse\"\303\001\202\323\344\223\002@\022>/v2/{table_name="
-          + "projects/*/instances/*/tables/*}:sampleR"
-          + "owKeys\212\323\344\223\002N\022:\n\ntable_name\022,{table_name="
+          + "\0132\032.google.protobuf.Timestamp\032\270\001\n\013CloseS"
+          + "tream\022\"\n\006status\030\001 \001(\0132\022.google.rpc.Statu"
+          + "s\022H\n\023continuation_tokens\030\002 \003(\0132+.google."
+          + "bigtable.v2.StreamContinuationToken\022;\n\016n"
+          + "ew_partitions\030\003 \003(\0132#.google.bigtable.v2"
+          + ".StreamPartitionB\017\n\rstream_record2\327\030\n\010Bi"
+          + "gtable\022\233\002\n\010ReadRows\022#.google.bigtable.v2"
+          + ".ReadRowsRequest\032$.google.bigtable.v2.Re"
+          + "adRowsResponse\"\301\001\202\323\344\223\002>\"9/v2/{table_name"
+          + "=projects/*/instances/*/tables/*}:readRo"
+          + "ws:\001*\212\323\344\223\002N\022:\n\ntable_name\022,{table_name=p"
+          + "rojects/*/instances/*/tables/*}\022\020\n\016app_p"
+          + "rofile_id\332A\ntable_name\332A\031table_name,app_"
+          + "profile_id0\001\022\254\002\n\rSampleRowKeys\022(.google."
+          + "bigtable.v2.SampleRowKeysRequest\032).googl"
+          + "e.bigtable.v2.SampleRowKeysResponse\"\303\001\202\323"
+          + "\344\223\002@\022>/v2/{table_name=projects/*/instanc"
+          + "es/*/tables/*}:sampleRowKeys\212\323\344\223\002N\022:\n\nta"
+          + "ble_name\022,{table_name=projects/*/instanc"
+          + "es/*/tables/*}\022\020\n\016app_profile_id\332A\ntable"
+          + "_name\332A\031table_name,app_profile_id0\001\022\301\002\n\t"
+          + "MutateRow\022$.google.bigtable.v2.MutateRow"
+          + "Request\032%.google.bigtable.v2.MutateRowRe"
+          + "sponse\"\346\001\202\323\344\223\002?\":/v2/{table_name=project"
+          + "s/*/instances/*/tables/*}:mutateRow:\001*\212\323"
+          + "\344\223\002N\022:\n\ntable_name\022,{table_name=projects"
+          + "/*/instances/*/tables/*}\022\020\n\016app_profile_"
+          + "id\332A\034table_name,row_key,mutations\332A+tabl"
+          + "e_name,row_key,mutations,app_profile_id\022"
+          + "\263\002\n\nMutateRows\022%.google.bigtable.v2.Muta"
+          + "teRowsRequest\032&.google.bigtable.v2.Mutat"
+          + "eRowsResponse\"\323\001\202\323\344\223\002@\";/v2/{table_name="
+          + "projects/*/instances/*/tables/*}:mutateR"
+          + "ows:\001*\212\323\344\223\002N\022:\n\ntable_name\022,{table_name="
           + "projects/*/instances/*/tables/*}\022\020\n\016app_"
-          + "profile_id\332A\ntable_name\332A\031table_name,app"
-          + "_profile_id0\001\022\301\002\n\tMutateRow\022$.google.big"
-          + "table.v2.MutateRowRequest\032%.google.bigta"
-          + "ble.v2.MutateRowResponse\"\346\001\202\323\344\223\002?\":/v2/{"
+          + "profile_id\332A\022table_name,entries\332A!table_"
+          + "name,entries,app_profile_id0\001\022\255\003\n\021CheckA"
+          + "ndMutateRow\022,.google.bigtable.v2.CheckAn"
+          + "dMutateRowRequest\032-.google.bigtable.v2.C"
+          + "heckAndMutateRowResponse\"\272\002\202\323\344\223\002G\"B/v2/{"
           + "table_name=projects/*/instances/*/tables"
-          + "/*}:mutateRow:\001*\212\323\344\223\002N\022:\n\ntable_name\022,{t"
-          + "able_name=projects/*/instances/*/tables/"
-          + "*}\022\020\n\016app_profile_id\332A\034table_name,row_ke"
-          + "y,mutations\332A+table_name,row_key,mutatio"
-          + "ns,app_profile_id\022\263\002\n\nMutateRows\022%.googl"
-          + "e.bigtable.v2.MutateRowsRequest\032&.google"
-          + ".bigtable.v2.MutateRowsResponse\"\323\001\202\323\344\223\002@"
-          + "\";/v2/{table_name=projects/*/instances/*"
-          + "/tables/*}:mutateRows:\001*\212\323\344\223\002N\022:\n\ntable_"
+          + "/*}:checkAndMutateRow:\001*\212\323\344\223\002N\022:\n\ntable_"
           + "name\022,{table_name=projects/*/instances/*"
-          + "/tables/*}\022\020\n\016app_profile_id\332A\022table_nam"
-          + "e,entries\332A!table_name,entries,app_profi"
-          + "le_id0\001\022\255\003\n\021CheckAndMutateRow\022,.google.b"
-          + "igtable.v2.CheckAndMutateRowRequest\032-.go"
-          + "ogle.bigtable.v2.CheckAndMutateRowRespon"
-          + "se\"\272\002\202\323\344\223\002G\"B/v2/{table_name=projects/*/"
-          + "instances/*/tables/*}:checkAndMutateRow:"
-          + "\001*\212\323\344\223\002N\022:\n\ntable_name\022,{table_name=proj"
-          + "ects/*/instances/*/tables/*}\022\020\n\016app_prof"
-          + "ile_id\332ABtable_name,row_key,predicate_fi"
-          + "lter,true_mutations,false_mutations\332AQta"
-          + "ble_name,row_key,predicate_filter,true_m"
-          + "utations,false_mutations,app_profile_id\022"
-          + "\356\001\n\013PingAndWarm\022&.google.bigtable.v2.Pin"
-          + "gAndWarmRequest\032\'.google.bigtable.v2.Pin"
-          + "gAndWarmResponse\"\215\001\202\323\344\223\002+\"&/v2/{name=pro"
-          + "jects/*/instances/*}:ping:\001*\212\323\344\223\0029\022%\n\004na"
-          + "me\022\035{name=projects/*/instances/*}\022\020\n\016app"
-          + "_profile_id\332A\004name\332A\023name,app_profile_id"
-          + "\022\335\002\n\022ReadModifyWriteRow\022-.google.bigtabl"
-          + "e.v2.ReadModifyWriteRowRequest\032..google."
-          + "bigtable.v2.ReadModifyWriteRowResponse\"\347"
-          + "\001\202\323\344\223\002H\"C/v2/{table_name=projects/*/inst"
-          + "ances/*/tables/*}:readModifyWriteRow:\001*\212"
-          + "\323\344\223\002N\022:\n\ntable_name\022,{table_name=project"
-          + "s/*/instances/*/tables/*}\022\020\n\016app_profile"
-          + "_id\332A\030table_name,row_key,rules\332A\'table_n"
-          + "ame,row_key,rules,app_profile_id\022\273\002\n%Gen"
-          + "erateInitialChangeStreamPartitions\022@.goo"
-          + "gle.bigtable.v2.GenerateInitialChangeStr"
-          + "eamPartitionsRequest\032A.google.bigtable.v"
-          + "2.GenerateInitialChangeStreamPartitionsR"
-          + "esponse\"\212\001\202\323\344\223\002[\"V/v2/{table_name=projec"
-          + "ts/*/instances/*/tables/*}:generateIniti"
-          + "alChangeStreamPartitions:\001*\332A\ntable_name"
-          + "\332A\031table_name,app_profile_id0\001\022\346\001\n\020ReadC"
-          + "hangeStream\022+.google.bigtable.v2.ReadCha"
-          + "ngeStreamRequest\032,.google.bigtable.v2.Re"
-          + "adChangeStreamResponse\"u\202\323\344\223\002F\"A/v2/{tab"
-          + "le_name=projects/*/instances/*/tables/*}"
-          + ":readChangeStream:\001*\332A\ntable_name\332A\031tabl"
-          + "e_name,app_profile_id0\001\032\333\002\312A\027bigtable.go"
-          + "ogleapis.com\322A\275\002https://www.googleapis.c"
-          + "om/auth/bigtable.data,https://www.google"
-          + "apis.com/auth/bigtable.data.readonly,htt"
-          + "ps://www.googleapis.com/auth/cloud-bigta"
-          + "ble.data,https://www.googleapis.com/auth"
-          + "/cloud-bigtable.data.readonly,https://ww"
-          + "w.googleapis.com/auth/cloud-platform,htt"
-          + "ps://www.googleapis.com/auth/cloud-platf"
-          + "orm.read-onlyB\353\002\n\026com.google.bigtable.v2"
-          + "B\rBigtableProtoP\001Z:google.golang.org/gen"
-          + "proto/googleapis/bigtable/v2;bigtable\252\002\030"
-          + "Google.Cloud.Bigtable.V2\312\002\030Google\\Cloud\\"
-          + "Bigtable\\V2\352\002\033Google::Cloud::Bigtable::V"
-          + "2\352AP\n%bigtableadmin.googleapis.com/Insta"
-          + "nce\022\'projects/{project}/instances/{insta"
-          + "nce}\352A\\\n\"bigtableadmin.googleapis.com/Ta"
-          + "ble\0226projects/{project}/instances/{insta"
-          + "nce}/tables/{table}b\006proto3"
+          + "/tables/*}\022\020\n\016app_profile_id\332ABtable_nam"
+          + "e,row_key,predicate_filter,true_mutation"
+          + "s,false_mutations\332AQtable_name,row_key,p"
+          + "redicate_filter,true_mutations,false_mut"
+          + "ations,app_profile_id\022\356\001\n\013PingAndWarm\022&."
+          + "google.bigtable.v2.PingAndWarmRequest\032\'."
+          + "google.bigtable.v2.PingAndWarmResponse\"\215"
+          + "\001\202\323\344\223\002+\"&/v2/{name=projects/*/instances/"
+          + "*}:ping:\001*\212\323\344\223\0029\022%\n\004name\022\035{name=projects"
+          + "/*/instances/*}\022\020\n\016app_profile_id\332A\004name"
+          + "\332A\023name,app_profile_id\022\335\002\n\022ReadModifyWri"
+          + "teRow\022-.google.bigtable.v2.ReadModifyWri"
+          + "teRowRequest\032..google.bigtable.v2.ReadMo"
+          + "difyWriteRowResponse\"\347\001\202\323\344\223\002H\"C/v2/{tabl"
+          + "e_name=projects/*/instances/*/tables/*}:"
+          + "readModifyWriteRow:\001*\212\323\344\223\002N\022:\n\ntable_nam"
+          + "e\022,{table_name=projects/*/instances/*/ta"
+          + "bles/*}\022\020\n\016app_profile_id\332A\030table_name,r"
+          + "ow_key,rules\332A\'table_name,row_key,rules,"
+          + "app_profile_id\022\273\002\n%GenerateInitialChange"
+          + "StreamPartitions\022@.google.bigtable.v2.Ge"
+          + "nerateInitialChangeStreamPartitionsReque"
+          + "st\032A.google.bigtable.v2.GenerateInitialC"
+          + "hangeStreamPartitionsResponse\"\212\001\202\323\344\223\002[\"V"
+          + "/v2/{table_name=projects/*/instances/*/t"
+          + "ables/*}:generateInitialChangeStreamPart"
+          + "itions:\001*\332A\ntable_name\332A\031table_name,app_"
+          + "profile_id0\001\022\346\001\n\020ReadChangeStream\022+.goog"
+          + "le.bigtable.v2.ReadChangeStreamRequest\032,"
+          + ".google.bigtable.v2.ReadChangeStreamResp"
+          + "onse\"u\202\323\344\223\002F\"A/v2/{table_name=projects/*"
+          + "/instances/*/tables/*}:readChangeStream:"
+          + "\001*\332A\ntable_name\332A\031table_name,app_profile"
+          + "_id0\001\032\333\002\312A\027bigtable.googleapis.com\322A\275\002ht"
+          + "tps://www.googleapis.com/auth/bigtable.d"
+          + "ata,https://www.googleapis.com/auth/bigt"
+          + "able.data.readonly,https://www.googleapi"
+          + "s.com/auth/cloud-bigtable.data,https://w"
+          + "ww.googleapis.com/auth/cloud-bigtable.da"
+          + "ta.readonly,https://www.googleapis.com/a"
+          + "uth/cloud-platform,https://www.googleapi"
+          + "s.com/auth/cloud-platform.read-onlyB\353\002\n\026"
+          + "com.google.bigtable.v2B\rBigtableProtoP\001Z"
+          + ":google.golang.org/genproto/googleapis/b"
+          + "igtable/v2;bigtable\252\002\030Google.Cloud.Bigta"
+          + "ble.V2\312\002\030Google\\Cloud\\Bigtable\\V2\352\002\033Goog"
+          + "le::Cloud::Bigtable::V2\352AP\n%bigtableadmi"
+          + "n.googleapis.com/Instance\022\'projects/{pro"
+          + "ject}/instances/{instance}\352A\\\n\"bigtablea"
+          + "dmin.googleapis.com/Table\0226projects/{pro"
+          + "ject}/instances/{instance}/tables/{table"
+          + "}b\006proto3"
     };
     descriptor =
         com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
@@ -604,7 +606,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
         new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
             internal_static_google_bigtable_v2_ReadChangeStreamResponse_CloseStream_descriptor,
             new java.lang.String[] {
-              "Status", "ContinuationTokens",
+              "Status", "ContinuationTokens", "NewPartitions",
             });
     com.google.protobuf.ExtensionRegistry registry =
         com.google.protobuf.ExtensionRegistry.newInstance();
diff --git a/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/ReadChangeStreamResponse.java b/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/ReadChangeStreamResponse.java
index 083b170f36..0739e1101a 100644
--- a/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/ReadChangeStreamResponse.java
+++ b/proto-google-cloud-bigtable-v2/src/main/java/com/google/bigtable/v2/ReadChangeStreamResponse.java
@@ -6100,8 +6100,8 @@ public interface CloseStreamOrBuilder
      *
      *
      * 
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6111,8 +6111,8 @@ public interface CloseStreamOrBuilder * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6122,8 +6122,8 @@ public interface CloseStreamOrBuilder * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6133,8 +6133,8 @@ public interface CloseStreamOrBuilder * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6145,24 +6145,101 @@ public interface CloseStreamOrBuilder * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; */ com.google.bigtable.v2.StreamContinuationTokenOrBuilder getContinuationTokensOrBuilder( int index); + + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + java.util.List getNewPartitionsList(); + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + com.google.bigtable.v2.StreamPartition getNewPartitions(int index); + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + int getNewPartitionsCount(); + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + java.util.List + getNewPartitionsOrBuilderList(); + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + com.google.bigtable.v2.StreamPartitionOrBuilder getNewPartitionsOrBuilder(int index); } /** * * *
    * A message indicating that the client should stop reading from the stream.
-   * If status is OK and `continuation_tokens` is empty, the stream has finished
-   * (for example if there was an `end_time` specified).
-   * If `continuation_tokens` is present, then a change in partitioning requires
-   * the client to open a new stream for each token to resume reading.
+   * If status is OK and `continuation_tokens` & `new_partitions` are empty, the
+   * stream has finished (for example if there was an `end_time` specified).
+   * If `continuation_tokens` & `new_partitions` are present, then a change in
+   * partitioning requires the client to open a new stream for each token to
+   * resume reading. Example:
+   *                                  [B,      D) ends
+   *                                       |
+   *                                       v
+   *               new_partitions:  [A,  C) [C,  E)
+   * continuation_tokens.partitions:  [B,C) [C,D)
+   *                                  ^---^ ^---^
+   *                                  ^     ^
+   *                                  |     |
+   *                                  |     StreamContinuationToken 2
+   *                                  |
+   *                                  StreamContinuationToken 1
+   * To read the new partition [A,C), supply the continuation tokens whose
+   * ranges cover the new partition, for example ContinuationToken[A,B) &
+   * ContinuationToken[B,C).
    * 
* * Protobuf type {@code google.bigtable.v2.ReadChangeStreamResponse.CloseStream} @@ -6179,6 +6256,7 @@ private CloseStream(com.google.protobuf.GeneratedMessageV3.Builder builder) { private CloseStream() { continuationTokens_ = java.util.Collections.emptyList(); + newPartitions_ = java.util.Collections.emptyList(); } @java.lang.Override @@ -6261,8 +6339,8 @@ public com.google.rpc.StatusOrBuilder getStatusOrBuilder() { * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6276,8 +6354,8 @@ public com.google.rpc.StatusOrBuilder getStatusOrBuilder() { * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6291,8 +6369,8 @@ public com.google.rpc.StatusOrBuilder getStatusOrBuilder() { * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6305,8 +6383,8 @@ public int getContinuationTokensCount() { * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6319,8 +6397,8 @@ public com.google.bigtable.v2.StreamContinuationToken getContinuationTokens(int * * *
-     * If non-empty, contains the information needed to start reading the new
-     * partition(s) that contain segments of this partition's row range.
+     * If non-empty, contains the information needed to resume reading their
+     * associated partitions.
      * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6331,6 +6409,87 @@ public com.google.bigtable.v2.StreamContinuationTokenOrBuilder getContinuationTo return continuationTokens_.get(index); } + public static final int NEW_PARTITIONS_FIELD_NUMBER = 3; + + @SuppressWarnings("serial") + private java.util.List newPartitions_; + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + @java.lang.Override + public java.util.List getNewPartitionsList() { + return newPartitions_; + } + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + @java.lang.Override + public java.util.List + getNewPartitionsOrBuilderList() { + return newPartitions_; + } + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + @java.lang.Override + public int getNewPartitionsCount() { + return newPartitions_.size(); + } + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + @java.lang.Override + public com.google.bigtable.v2.StreamPartition getNewPartitions(int index) { + return newPartitions_.get(index); + } + /** + * + * + *
+     * If non-empty, contains the new partitions to start reading from, which
+     * are related to but not necessarily identical to the partitions for the
+     * above `continuation_tokens`.
+     * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + @java.lang.Override + public com.google.bigtable.v2.StreamPartitionOrBuilder getNewPartitionsOrBuilder(int index) { + return newPartitions_.get(index); + } + private byte memoizedIsInitialized = -1; @java.lang.Override @@ -6351,6 +6510,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io for (int i = 0; i < continuationTokens_.size(); i++) { output.writeMessage(2, continuationTokens_.get(i)); } + for (int i = 0; i < newPartitions_.size(); i++) { + output.writeMessage(3, newPartitions_.get(i)); + } getUnknownFields().writeTo(output); } @@ -6367,6 +6529,9 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream.computeMessageSize(2, continuationTokens_.get(i)); } + for (int i = 0; i < newPartitions_.size(); i++) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(3, newPartitions_.get(i)); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -6388,6 +6553,7 @@ public boolean equals(final java.lang.Object obj) { if (!getStatus().equals(other.getStatus())) return false; } if (!getContinuationTokensList().equals(other.getContinuationTokensList())) return false; + if (!getNewPartitionsList().equals(other.getNewPartitionsList())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -6407,6 +6573,10 @@ public int hashCode() { hash = (37 * hash) + CONTINUATION_TOKENS_FIELD_NUMBER; hash = (53 * hash) + getContinuationTokensList().hashCode(); } + if (getNewPartitionsCount() > 0) { + hash = (37 * hash) + NEW_PARTITIONS_FIELD_NUMBER; + hash = (53 * hash) + getNewPartitionsList().hashCode(); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -6514,10 +6684,25 @@ protected Builder newBuilderForType( * *
      * A message indicating that the client should stop reading from the stream.
-     * If status is OK and `continuation_tokens` is empty, the stream has finished
-     * (for example if there was an `end_time` specified).
-     * If `continuation_tokens` is present, then a change in partitioning requires
-     * the client to open a new stream for each token to resume reading.
+     * If status is OK and `continuation_tokens` & `new_partitions` are empty, the
+     * stream has finished (for example if there was an `end_time` specified).
+     * If `continuation_tokens` & `new_partitions` are present, then a change in
+     * partitioning requires the client to open a new stream for each token to
+     * resume reading. Example:
+     *                                  [B,      D) ends
+     *                                       |
+     *                                       v
+     *               new_partitions:  [A,  C) [C,  E)
+     * continuation_tokens.partitions:  [B,C) [C,D)
+     *                                  ^---^ ^---^
+     *                                  ^     ^
+     *                                  |     |
+     *                                  |     StreamContinuationToken 2
+     *                                  |
+     *                                  StreamContinuationToken 1
+     * To read the new partition [A,C), supply the continuation tokens whose
+     * ranges cover the new partition, for example ContinuationToken[A,B) &
+     * ContinuationToken[B,C).
      * 
* * Protobuf type {@code google.bigtable.v2.ReadChangeStreamResponse.CloseStream} @@ -6565,6 +6750,13 @@ public Builder clear() { continuationTokensBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000002); + if (newPartitionsBuilder_ == null) { + newPartitions_ = java.util.Collections.emptyList(); + } else { + newPartitions_ = null; + newPartitionsBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); return this; } @@ -6612,6 +6804,15 @@ private void buildPartialRepeatedFields( } else { result.continuationTokens_ = continuationTokensBuilder_.build(); } + if (newPartitionsBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0)) { + newPartitions_ = java.util.Collections.unmodifiableList(newPartitions_); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.newPartitions_ = newPartitions_; + } else { + result.newPartitions_ = newPartitionsBuilder_.build(); + } } private void buildPartial0( @@ -6701,6 +6902,33 @@ public Builder mergeFrom(com.google.bigtable.v2.ReadChangeStreamResponse.CloseSt } } } + if (newPartitionsBuilder_ == null) { + if (!other.newPartitions_.isEmpty()) { + if (newPartitions_.isEmpty()) { + newPartitions_ = other.newPartitions_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureNewPartitionsIsMutable(); + newPartitions_.addAll(other.newPartitions_); + } + onChanged(); + } + } else { + if (!other.newPartitions_.isEmpty()) { + if (newPartitionsBuilder_.isEmpty()) { + newPartitionsBuilder_.dispose(); + newPartitionsBuilder_ = null; + newPartitions_ = other.newPartitions_; + bitField0_ = (bitField0_ & ~0x00000004); + newPartitionsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders + ? getNewPartitionsFieldBuilder() + : null; + } else { + newPartitionsBuilder_.addAllMessages(other.newPartitions_); + } + } + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -6747,6 +6975,19 @@ public Builder mergeFrom( } break; } // case 18 + case 26: + { + com.google.bigtable.v2.StreamPartition m = + input.readMessage( + com.google.bigtable.v2.StreamPartition.parser(), extensionRegistry); + if (newPartitionsBuilder_ == null) { + ensureNewPartitionsIsMutable(); + newPartitions_.add(m); + } else { + newPartitionsBuilder_.addMessage(m); + } + break; + } // case 26 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -6962,8 +7203,8 @@ private void ensureContinuationTokensIsMutable() { * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6980,8 +7221,8 @@ private void ensureContinuationTokensIsMutable() { * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -6997,8 +7238,8 @@ public int getContinuationTokensCount() { * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7014,8 +7255,8 @@ public com.google.bigtable.v2.StreamContinuationToken getContinuationTokens(int * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7038,8 +7279,8 @@ public Builder setContinuationTokens( * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7059,8 +7300,8 @@ public Builder setContinuationTokens( * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7082,8 +7323,8 @@ public Builder addContinuationTokens(com.google.bigtable.v2.StreamContinuationTo * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7106,8 +7347,8 @@ public Builder addContinuationTokens( * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7127,8 +7368,8 @@ public Builder addContinuationTokens( * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7148,8 +7389,8 @@ public Builder addContinuationTokens( * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7169,8 +7410,8 @@ public Builder addAllContinuationTokens( * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7189,8 +7430,8 @@ public Builder clearContinuationTokens() { * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7209,8 +7450,8 @@ public Builder removeContinuationTokens(int index) { * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7223,8 +7464,8 @@ public com.google.bigtable.v2.StreamContinuationToken.Builder getContinuationTok * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7241,8 +7482,8 @@ public com.google.bigtable.v2.StreamContinuationTokenOrBuilder getContinuationTo * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7259,8 +7500,8 @@ public com.google.bigtable.v2.StreamContinuationTokenOrBuilder getContinuationTo * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7273,8 +7514,8 @@ public com.google.bigtable.v2.StreamContinuationToken.Builder addContinuationTok * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7288,8 +7529,8 @@ public com.google.bigtable.v2.StreamContinuationToken.Builder addContinuationTok * * *
-       * If non-empty, contains the information needed to start reading the new
-       * partition(s) that contain segments of this partition's row range.
+       * If non-empty, contains the information needed to resume reading their
+       * associated partitions.
        * 
* * repeated .google.bigtable.v2.StreamContinuationToken continuation_tokens = 2; @@ -7319,6 +7560,396 @@ public com.google.bigtable.v2.StreamContinuationToken.Builder addContinuationTok return continuationTokensBuilder_; } + private java.util.List newPartitions_ = + java.util.Collections.emptyList(); + + private void ensureNewPartitionsIsMutable() { + if (!((bitField0_ & 0x00000004) != 0)) { + newPartitions_ = + new java.util.ArrayList(newPartitions_); + bitField0_ |= 0x00000004; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.google.bigtable.v2.StreamPartition, + com.google.bigtable.v2.StreamPartition.Builder, + com.google.bigtable.v2.StreamPartitionOrBuilder> + newPartitionsBuilder_; + + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public java.util.List getNewPartitionsList() { + if (newPartitionsBuilder_ == null) { + return java.util.Collections.unmodifiableList(newPartitions_); + } else { + return newPartitionsBuilder_.getMessageList(); + } + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public int getNewPartitionsCount() { + if (newPartitionsBuilder_ == null) { + return newPartitions_.size(); + } else { + return newPartitionsBuilder_.getCount(); + } + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public com.google.bigtable.v2.StreamPartition getNewPartitions(int index) { + if (newPartitionsBuilder_ == null) { + return newPartitions_.get(index); + } else { + return newPartitionsBuilder_.getMessage(index); + } + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder setNewPartitions(int index, com.google.bigtable.v2.StreamPartition value) { + if (newPartitionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNewPartitionsIsMutable(); + newPartitions_.set(index, value); + onChanged(); + } else { + newPartitionsBuilder_.setMessage(index, value); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder setNewPartitions( + int index, com.google.bigtable.v2.StreamPartition.Builder builderForValue) { + if (newPartitionsBuilder_ == null) { + ensureNewPartitionsIsMutable(); + newPartitions_.set(index, builderForValue.build()); + onChanged(); + } else { + newPartitionsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder addNewPartitions(com.google.bigtable.v2.StreamPartition value) { + if (newPartitionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNewPartitionsIsMutable(); + newPartitions_.add(value); + onChanged(); + } else { + newPartitionsBuilder_.addMessage(value); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder addNewPartitions(int index, com.google.bigtable.v2.StreamPartition value) { + if (newPartitionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNewPartitionsIsMutable(); + newPartitions_.add(index, value); + onChanged(); + } else { + newPartitionsBuilder_.addMessage(index, value); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder addNewPartitions( + com.google.bigtable.v2.StreamPartition.Builder builderForValue) { + if (newPartitionsBuilder_ == null) { + ensureNewPartitionsIsMutable(); + newPartitions_.add(builderForValue.build()); + onChanged(); + } else { + newPartitionsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder addNewPartitions( + int index, com.google.bigtable.v2.StreamPartition.Builder builderForValue) { + if (newPartitionsBuilder_ == null) { + ensureNewPartitionsIsMutable(); + newPartitions_.add(index, builderForValue.build()); + onChanged(); + } else { + newPartitionsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder addAllNewPartitions( + java.lang.Iterable values) { + if (newPartitionsBuilder_ == null) { + ensureNewPartitionsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, newPartitions_); + onChanged(); + } else { + newPartitionsBuilder_.addAllMessages(values); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder clearNewPartitions() { + if (newPartitionsBuilder_ == null) { + newPartitions_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + } else { + newPartitionsBuilder_.clear(); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public Builder removeNewPartitions(int index) { + if (newPartitionsBuilder_ == null) { + ensureNewPartitionsIsMutable(); + newPartitions_.remove(index); + onChanged(); + } else { + newPartitionsBuilder_.remove(index); + } + return this; + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public com.google.bigtable.v2.StreamPartition.Builder getNewPartitionsBuilder(int index) { + return getNewPartitionsFieldBuilder().getBuilder(index); + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public com.google.bigtable.v2.StreamPartitionOrBuilder getNewPartitionsOrBuilder(int index) { + if (newPartitionsBuilder_ == null) { + return newPartitions_.get(index); + } else { + return newPartitionsBuilder_.getMessageOrBuilder(index); + } + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public java.util.List + getNewPartitionsOrBuilderList() { + if (newPartitionsBuilder_ != null) { + return newPartitionsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(newPartitions_); + } + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public com.google.bigtable.v2.StreamPartition.Builder addNewPartitionsBuilder() { + return getNewPartitionsFieldBuilder() + .addBuilder(com.google.bigtable.v2.StreamPartition.getDefaultInstance()); + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public com.google.bigtable.v2.StreamPartition.Builder addNewPartitionsBuilder(int index) { + return getNewPartitionsFieldBuilder() + .addBuilder(index, com.google.bigtable.v2.StreamPartition.getDefaultInstance()); + } + /** + * + * + *
+       * If non-empty, contains the new partitions to start reading from, which
+       * are related to but not necessarily identical to the partitions for the
+       * above `continuation_tokens`.
+       * 
+ * + * repeated .google.bigtable.v2.StreamPartition new_partitions = 3; + */ + public java.util.List + getNewPartitionsBuilderList() { + return getNewPartitionsFieldBuilder().getBuilderList(); + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + com.google.bigtable.v2.StreamPartition, + com.google.bigtable.v2.StreamPartition.Builder, + com.google.bigtable.v2.StreamPartitionOrBuilder> + getNewPartitionsFieldBuilder() { + if (newPartitionsBuilder_ == null) { + newPartitionsBuilder_ = + new com.google.protobuf.RepeatedFieldBuilderV3< + com.google.bigtable.v2.StreamPartition, + com.google.bigtable.v2.StreamPartition.Builder, + com.google.bigtable.v2.StreamPartitionOrBuilder>( + newPartitions_, + ((bitField0_ & 0x00000004) != 0), + getParentForChildren(), + isClean()); + newPartitions_ = null; + } + return newPartitionsBuilder_; + } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { diff --git a/proto-google-cloud-bigtable-v2/src/main/proto/google/bigtable/v2/bigtable.proto b/proto-google-cloud-bigtable-v2/src/main/proto/google/bigtable/v2/bigtable.proto index c85e0cfc8c..098d17e3e7 100644 --- a/proto-google-cloud-bigtable-v2/src/main/proto/google/bigtable/v2/bigtable.proto +++ b/proto-google-cloud-bigtable-v2/src/main/proto/google/bigtable/v2/bigtable.proto @@ -788,17 +788,37 @@ message ReadChangeStreamResponse { } // A message indicating that the client should stop reading from the stream. - // If status is OK and `continuation_tokens` is empty, the stream has finished - // (for example if there was an `end_time` specified). - // If `continuation_tokens` is present, then a change in partitioning requires - // the client to open a new stream for each token to resume reading. + // If status is OK and `continuation_tokens` & `new_partitions` are empty, the + // stream has finished (for example if there was an `end_time` specified). + // If `continuation_tokens` & `new_partitions` are present, then a change in + // partitioning requires the client to open a new stream for each token to + // resume reading. Example: + // [B, D) ends + // | + // v + // new_partitions: [A, C) [C, E) + // continuation_tokens.partitions: [B,C) [C,D) + // ^---^ ^---^ + // ^ ^ + // | | + // | StreamContinuationToken 2 + // | + // StreamContinuationToken 1 + // To read the new partition [A,C), supply the continuation tokens whose + // ranges cover the new partition, for example ContinuationToken[A,B) & + // ContinuationToken[B,C). message CloseStream { // The status of the stream. google.rpc.Status status = 1; - // If non-empty, contains the information needed to start reading the new - // partition(s) that contain segments of this partition's row range. + // If non-empty, contains the information needed to resume reading their + // associated partitions. repeated StreamContinuationToken continuation_tokens = 2; + + // If non-empty, contains the new partitions to start reading from, which + // are related to but not necessarily identical to the partitions for the + // above `continuation_tokens`. + repeated StreamPartition new_partitions = 3; } // The data or control message on the stream. diff --git a/renovate.json b/renovate.json index 2543edb1a8..7494258c9a 100644 --- a/renovate.json +++ b/renovate.json @@ -68,6 +68,28 @@ "^com.fasterxml.jackson.core" ], "groupName": "jackson dependencies" + }, + { + "packagePatterns": [ + "^com.google.cloud:google-cloud-shared-dependencies", + "^com.google.protobuf:protoc", + "^io.grpc:protoc-gen-grpc-java" + ], + "groupName": "shared dependencies" + } + ], + "regexManagers": [ + { + "fileMatch": ["^pom\\.xml$"], + "matchStrings": ["\\(?.*?)\\<\\/grpc\\.version\\>"], + "depNameTemplate": "io.grpc:protoc-gen-grpc-java", + "datasourceTemplate": "maven" + }, + { + "fileMatch": ["^pom\\.xml$"], + "matchStrings": ["\\(?.*?)\\<\\/protobuf\\.version\\>"], + "depNameTemplate": "com.google.protobuf:protoc", + "datasourceTemplate": "maven" } ], "semanticCommits": true, diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index d4cb9fac5f..7e407955ed 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-bigtable - 2.19.1 + 2.20.2 diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml index 1f8ff485ac..954eb06312 100644 --- a/samples/native-image-sample/pom.xml +++ b/samples/native-image-sample/pom.xml @@ -29,7 +29,7 @@ com.google.cloud libraries-bom - 26.8.0 + 26.11.0 pom import diff --git a/samples/pom.xml b/samples/pom.xml index 4254f54811..e05832ffc6 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -39,7 +39,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.0.0 + 3.1.1 true diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index af5085f6a7..1011de9c95 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-bigtable - 2.19.2 + 2.20.3 diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index f58844f347..d072f99023 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.8.0 + 26.11.0 pom import diff --git a/test-proxy/pom.xml b/test-proxy/pom.xml index e2326f96d7..162785dc7e 100644 --- a/test-proxy/pom.xml +++ b/test-proxy/pom.xml @@ -12,11 +12,11 @@ google-cloud-bigtable-parent com.google.cloud - 2.19.2 + 2.20.3 - 2.19.2 + 2.20.3 diff --git a/test-proxy/src/main/java/com/google/cloud/bigtable/testproxy/CbtTestProxy.java b/test-proxy/src/main/java/com/google/cloud/bigtable/testproxy/CbtTestProxy.java index c668ca5e30..c14d4b4186 100644 --- a/test-proxy/src/main/java/com/google/cloud/bigtable/testproxy/CbtTestProxy.java +++ b/test-proxy/src/main/java/com/google/cloud/bigtable/testproxy/CbtTestProxy.java @@ -60,6 +60,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -488,7 +489,8 @@ public void readRows(ReadRowsRequest request, StreamObserver respons /** * Helper method to convert row from type com.google.cloud.bigtable.data.v2.models.Row to type * com.google.bigtable.v2.Row. After conversion, row cells within the same column and family are - * grouped and ordered; but the ordering of family and qualifier is not preserved. + * grouped and ordered; the ordering of qualifiers within the same family is preserved; but the + * ordering of families is not (the original order is not specified after all). * * @param row Logical row of type com.google.cloud.bigtable.data.v2.models.Row * @return the converted row in RowResult Builder @@ -502,7 +504,9 @@ private static RowResult.Builder convertRowResult( row.getCells().stream() .collect( Collectors.groupingBy( - RowCell::getFamily, Collectors.groupingBy(RowCell::getQualifier))); + RowCell::getFamily, + Collectors.groupingBy( + RowCell::getQualifier, LinkedHashMap::new, Collectors.toList()))); for (Map.Entry>> e : grouped.entrySet()) { Family.Builder family = rowBuilder.addFamiliesBuilder().setName(e.getKey()); diff --git a/versions.txt b/versions.txt index 98b9735ca9..10506013e2 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -google-cloud-bigtable:2.19.2:2.19.2 -grpc-google-cloud-bigtable-admin-v2:2.19.2:2.19.2 -grpc-google-cloud-bigtable-v2:2.19.2:2.19.2 -proto-google-cloud-bigtable-admin-v2:2.19.2:2.19.2 -proto-google-cloud-bigtable-v2:2.19.2:2.19.2 -google-cloud-bigtable-emulator:0.156.2:0.156.2 -google-cloud-bigtable-emulator-core:2.19.2:2.19.2 +google-cloud-bigtable:2.20.3:2.20.3 +grpc-google-cloud-bigtable-admin-v2:2.20.3:2.20.3 +grpc-google-cloud-bigtable-v2:2.20.3:2.20.3 +proto-google-cloud-bigtable-admin-v2:2.20.3:2.20.3 +proto-google-cloud-bigtable-v2:2.20.3:2.20.3 +google-cloud-bigtable-emulator:0.157.3:0.157.3 +google-cloud-bigtable-emulator-core:2.20.3:2.20.3