diff --git a/CHANGELOG.md b/CHANGELOG.md
index d8d5352c9907..1a97183677b7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [2.23.4](https://github.com/googleapis/java-bigtable/compare/v2.23.3...v2.23.4) (2023-11-06)
+
+
+### Bug Fixes
+
+* A rare race condition in the row merger ([#1939](https://github.com/googleapis/java-bigtable/issues/1939)) ([#1988](https://github.com/googleapis/java-bigtable/issues/1988)) ([31b084a](https://github.com/googleapis/java-bigtable/commit/31b084abc9c4d609314f232e616b59a4016b991f))
+
## [2.23.3](https://github.com/googleapis/java-bigtable/compare/v2.23.2...v2.23.3) (2023-06-08)
diff --git a/README.md b/README.md
index d27cdd42de21..236d539c949c 100644
--- a/README.md
+++ b/README.md
@@ -50,20 +50,20 @@ If you are using Maven without the 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.16.0')
+implementation platform('com.google.cloud:libraries-bom:26.26.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.23.2'
+implementation 'com.google.cloud:google-cloud-bigtable:2.29.0'
```
If you are using SBT, add this to your dependencies:
```Scala
-libraryDependencies += "com.google.cloud" % "google-cloud-bigtable" % "2.23.2"
+libraryDependencies += "com.google.cloud" % "google-cloud-bigtable" % "2.29.0"
```
@@ -609,7 +609,7 @@ 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://central.sonatype.com/artifact/com.google.cloud/google-cloud-bigtable/2.23.2
+[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-bigtable/2.29.0
[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
diff --git a/google-cloud-bigtable-bom/pom.xml b/google-cloud-bigtable-bom/pom.xml
index 1fa3e916ee8b..9c58071b35f8 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.23.3
+ 2.23.4
pom
com.google.cloud
@@ -63,42 +63,42 @@
com.google.cloud
google-cloud-bigtable
- 2.23.3
+ 2.23.4
com.google.cloud
google-cloud-bigtable-emulator
- 0.160.3
+ 0.160.4
com.google.cloud
google-cloud-bigtable-emulator-core
- 0.160.3
+ 0.160.4
com.google.api.grpc
grpc-google-cloud-bigtable-admin-v2
- 2.23.3
+ 2.23.4
com.google.api.grpc
grpc-google-cloud-bigtable-v2
- 2.23.3
+ 2.23.4
com.google.api.grpc
proto-google-cloud-bigtable-admin-v2
- 2.23.3
+ 2.23.4
com.google.api.grpc
proto-google-cloud-bigtable-v2
- 2.23.3
+ 2.23.4
com.google.cloud
google-cloud-bigtable-stats
- 2.23.3
+ 2.23.4
diff --git a/google-cloud-bigtable-deps-bom/pom.xml b/google-cloud-bigtable-deps-bom/pom.xml
index 6064d6e36dd5..f9b5792f4055 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.23.3
+ 2.23.4
pom
diff --git a/google-cloud-bigtable-emulator-core/pom.xml b/google-cloud-bigtable-emulator-core/pom.xml
index 8443f6c27aa7..5ff394493568 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.23.3
+ 2.23.4
google-cloud-bigtable-emulator-core
- 0.160.3
+ 0.160.4
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 e3d959c63ace..e3acaed458d0 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.160.3
+ 0.160.4
Google Cloud Java - Bigtable Emulator
https://github.com/googleapis/java-bigtable
@@ -14,7 +14,7 @@
com.google.cloud
google-cloud-bigtable-parent
- 2.23.3
+ 2.23.4
scm:git:git@github.com:googleapis/java-bigtable.git
@@ -81,14 +81,14 @@
com.google.cloud
google-cloud-bigtable-deps-bom
- 2.23.3
+ 2.23.4
pom
import
com.google.cloud
google-cloud-bigtable-bom
- 2.23.3
+ 2.23.4
pom
import
@@ -99,7 +99,7 @@
com.google.cloud
google-cloud-bigtable-emulator-core
- 0.160.3
+ 0.160.4
diff --git a/google-cloud-bigtable-stats/pom.xml b/google-cloud-bigtable-stats/pom.xml
index 593d776dcdad..e0fef5c7ddbe 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.23.3
+ 2.23.4
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.23.3
+ 2.23.4
Experimental project to shade OpenCensus dependencies.
@@ -21,7 +21,7 @@
com.google.cloud
google-cloud-bigtable-deps-bom
- 2.23.3
+ 2.23.4
pom
import
diff --git a/google-cloud-bigtable/pom.xml b/google-cloud-bigtable/pom.xml
index 073bbea76444..d23d5ed365f7 100644
--- a/google-cloud-bigtable/pom.xml
+++ b/google-cloud-bigtable/pom.xml
@@ -2,7 +2,7 @@
4.0.0
google-cloud-bigtable
- 2.23.3
+ 2.23.4
jar
Google Cloud Bigtable
https://github.com/googleapis/java-bigtable
@@ -12,11 +12,11 @@
com.google.cloud
google-cloud-bigtable-parent
- 2.23.3
+ 2.23.4
- 2.23.3
+ 2.23.4
google-cloud-bigtable
@@ -47,14 +47,14 @@
com.google.cloud
google-cloud-bigtable-deps-bom
- 2.23.3
+ 2.23.4
pom
import
com.google.cloud
google-cloud-bigtable-bom
- 2.23.3
+ 2.23.4
pom
import
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 0b855fbc422c..99e7373c194f 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.23.3";
+ public static String VERSION = "2.23.4";
// {x-version-update-end}
}
diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserver.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserver.java
index 6f2440fff7e5..3a5458836fc2 100644
--- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserver.java
+++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserver.java
@@ -277,7 +277,7 @@ private void deliverUnsafe() {
// Optimization: the inner loop will eager process any accumulated state, so reset the lock
// for just this iteration. (If another event occurs during processing, it can increment the
// lock to enqueue another iteration).
- lock.lazySet(1);
+ lock.set(1);
// Process the upstream message if one exists.
pollUpstream();
diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java
index 1b833f5c0639..e783352bf065 100644
--- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java
+++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BigtableTracerCallableTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.fail;
import com.google.api.gax.rpc.ClientContext;
+import com.google.api.gax.rpc.ServerStream;
import com.google.api.gax.rpc.UnavailableException;
import com.google.bigtable.v2.BigtableGrpc.BigtableImplBase;
import com.google.bigtable.v2.CheckAndMutateRowRequest;
@@ -54,7 +55,6 @@
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
-import io.opencensus.impl.stats.StatsComponentImpl;
import io.opencensus.stats.StatsComponent;
import io.opencensus.tags.TagKey;
import io.opencensus.tags.TagValue;
@@ -74,7 +74,7 @@ public class BigtableTracerCallableTest {
private FakeService fakeService = new FakeService();
- private final StatsComponent localStats = new StatsComponentImpl();
+ private final StatsComponent localStats = new SimpleStatsComponent();
private EnhancedBigtableStub stub;
private EnhancedBigtableStub noHeaderStub;
private int attempts;
@@ -157,10 +157,9 @@ public void tearDown() {
}
@Test
- public void testGFELatencyMetricReadRows() throws InterruptedException {
- stub.readRowsCallable().call(Query.create(TABLE_ID));
-
- Thread.sleep(WAIT_FOR_METRICS_TIME_MS);
+ public void testGFELatencyMetricReadRows() {
+ ServerStream> call = stub.readRowsCallable().call(Query.create(TABLE_ID));
+ call.forEach(r -> {});
long latency =
StatsTestUtils.getAggregationValueAsLong(
diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracerTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracerTest.java
index 3bc283a7f747..443b87a26d08 100644
--- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracerTest.java
+++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/BuiltinMetricsTracerTest.java
@@ -109,6 +109,7 @@ public class BuiltinMetricsTracerTest {
private static final long FAKE_SERVER_TIMING = 50;
private static final long SERVER_LATENCY = 100;
private static final long APPLICATION_LATENCY = 200;
+ private static final long SLEEP_VARIABILITY = 15;
private static final long CHANNEL_BLOCKING_LATENCY = 75;
@@ -353,7 +354,11 @@ public void onComplete() {
.recordOperation(status.capture(), tableId.capture(), zone.capture(), cluster.capture());
assertThat(counter.get()).isEqualTo(fakeService.getResponseCounter().get());
- assertThat(applicationLatency.getValue()).isAtLeast(APPLICATION_LATENCY * counter.get());
+ // Thread.sleep might not sleep for the requested amount depending on the interrupt period
+ // defined by the OS.
+ // On linux this is ~1ms but on windows may be as high as 15-20ms.
+ assertThat(applicationLatency.getValue())
+ .isAtLeast((APPLICATION_LATENCY - SLEEP_VARIABILITY) * counter.get());
assertThat(applicationLatency.getValue())
.isAtMost(operationLatency.getValue() - SERVER_LATENCY);
}
diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java
index b1b966ee9da5..5460d4fecaf1 100644
--- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java
+++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java
@@ -54,7 +54,7 @@
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
-import io.opencensus.impl.stats.StatsComponentImpl;
+import io.opencensus.stats.StatsComponent;
import io.opencensus.tags.TagKey;
import io.opencensus.tags.TagValue;
import io.opencensus.tags.Tags;
@@ -84,6 +84,7 @@ public class MetricsTracerTest {
private static final String INSTANCE_ID = "fake-instance";
private static final String APP_PROFILE_ID = "default";
private static final String TABLE_ID = "fake-table";
+ private static final long SLEEP_VARIABILITY = 15;
private static final ReadRowsResponse DEFAULT_READ_ROWS_RESPONSES =
ReadRowsResponse.newBuilder()
@@ -104,7 +105,7 @@ public class MetricsTracerTest {
@Mock(answer = Answers.CALLS_REAL_METHODS)
private BigtableGrpc.BigtableImplBase mockService;
- private final StatsComponentImpl localStats = new StatsComponentImpl();
+ private final StatsComponent localStats = new SimpleStatsComponent();
private EnhancedBigtableStub stub;
private BigtableDataSettings settings;
@@ -156,9 +157,6 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
Lists.newArrayList(stub.readRowsCallable().call(Query.create(TABLE_ID)));
long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
- // Give OpenCensus a chance to update the views asynchronously.
- Thread.sleep(100);
-
long opLatency =
StatsTestUtils.getAggregationValueAsLong(
localStats,
@@ -192,9 +190,6 @@ public Object answer(InvocationOnMock invocation) {
Lists.newArrayList(stub.readRowsCallable().call(Query.create(TABLE_ID)));
Lists.newArrayList(stub.readRowsCallable().call(Query.create(TABLE_ID)));
- // Give OpenCensus a chance to update the views asynchronously.
- Thread.sleep(100);
-
long opLatency =
StatsTestUtils.getAggregationValueAsLong(
localStats,
@@ -246,8 +241,6 @@ public void testReadRowsFirstRow() throws InterruptedException {
}
long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
- // Give OpenCensus a chance to update the views asynchronously.
- Thread.sleep(100);
executor.shutdown();
long firstRowLatency =
@@ -259,7 +252,10 @@ public void testReadRowsFirstRow() throws InterruptedException {
INSTANCE_ID,
APP_PROFILE_ID);
- assertThat(firstRowLatency).isIn(Range.closed(beforeSleep, elapsed - afterSleep));
+ assertThat(firstRowLatency)
+ .isIn(
+ Range.closed(
+ beforeSleep - SLEEP_VARIABILITY, elapsed - afterSleep + SLEEP_VARIABILITY));
}
@Test
@@ -291,9 +287,6 @@ public Object answer(InvocationOnMock invocation) {
Lists.newArrayList(stub.readRowsCallable().call(Query.create(TABLE_ID)));
- // Give OpenCensus a chance to update the views asynchronously.
- Thread.sleep(100);
-
long opLatency =
StatsTestUtils.getAggregationValueAsLong(
localStats,
@@ -340,9 +333,6 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
Lists.newArrayList(stub.readRowsCallable().call(Query.create(TABLE_ID)));
long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
- // Give OpenCensus a chance to update the views asynchronously.
- Thread.sleep(100);
-
long attemptLatency =
StatsTestUtils.getAggregationValueAsLong(
localStats,
@@ -359,12 +349,11 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
}
@Test
- public void testInvalidRequest() throws InterruptedException {
+ public void testInvalidRequest() {
try {
stub.bulkMutateRowsCallable().call(BulkMutation.create(TABLE_ID));
Assert.fail("Invalid request should throw exception");
} catch (IllegalStateException e) {
- Thread.sleep(100);
// Verify that the latency is recorded with an error code (in this case UNKNOWN)
long attemptLatency =
StatsTestUtils.getAggregationValueAsLong(
@@ -402,9 +391,6 @@ public Object answer(InvocationOnMock invocation) {
batcher.add(ByteString.copyFromUtf8("row1"));
batcher.sendOutstanding();
- // Give OpenCensus a chance to update the views asynchronously.
- Thread.sleep(100);
-
long throttledTimeMetric =
StatsTestUtils.getAggregationValueAsLong(
localStats,
@@ -469,7 +455,6 @@ public Object answer(InvocationOnMock invocation) {
batcher.add(RowMutationEntry.create("key"));
batcher.sendOutstanding();
- Thread.sleep(100);
long throttledTimeMetric =
StatsTestUtils.getAggregationValueAsLong(
localStats,
diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/SimpleStatsComponent.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/SimpleStatsComponent.java
new file mode 100644
index 000000000000..99aed9c3b4f4
--- /dev/null
+++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/SimpleStatsComponent.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.cloud.bigtable.data.v2.stub.metrics;
+
+import io.opencensus.implcore.common.MillisClock;
+import io.opencensus.implcore.internal.SimpleEventQueue;
+import io.opencensus.implcore.stats.StatsComponentImplBase;
+
+/** A StatsComponent implementation for testing that executes all events inline. */
+public class SimpleStatsComponent extends StatsComponentImplBase {
+ public SimpleStatsComponent() {
+ super(new SimpleEventQueue(), MillisClock.getInstance());
+ }
+}
diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserverTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserverTest.java
index 426c27f5a311..23df3726d373 100644
--- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserverTest.java
+++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/gaxx/reframing/ReframingResponseObserverTest.java
@@ -15,9 +15,12 @@
*/
package com.google.cloud.bigtable.gaxx.reframing;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import com.google.api.gax.rpc.StreamController;
import com.google.cloud.bigtable.gaxx.testing.FakeStreamingApi.ServerStreamingStashCallable;
import com.google.cloud.bigtable.gaxx.testing.FakeStreamingApi.ServerStreamingStashCallable.StreamControllerStash;
+import com.google.cloud.bigtable.gaxx.testing.MockStreamingApi;
import com.google.cloud.bigtable.gaxx.testing.MockStreamingApi.MockResponseObserver;
import com.google.cloud.bigtable.gaxx.testing.MockStreamingApi.MockServerStreamingCall;
import com.google.cloud.bigtable.gaxx.testing.MockStreamingApi.MockServerStreamingCallable;
@@ -27,9 +30,13 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Queues;
import com.google.common.truth.Truth;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Queue;
+import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -431,6 +438,120 @@ public String pop() {
Truth.assertThat(finalError.getSuppressed()[0].getCause()).isSameInstanceAs(fakeCancelError);
}
+ /**
+ * Test race between a request() and onComplete (b/295866356). This will stress the concurrency
+ * primitives in deliver() by running a many iterations across many threads. Some race conditions
+ * are very subtle and are very rare, so bugs in the implementation would present themselves as
+ * flakes in this test. All flakes of this test should be investigated as a failure.
+ */
+ @Test
+ public void testRequestAndCompleteRaceCondition() throws Throwable {
+ int concurrency = 20;
+ int iterations = 20_000;
+
+ ExecutorService executor = Executors.newFixedThreadPool(concurrency);
+
+ List> results = new ArrayList<>();
+
+ for (int i = 0; i < concurrency; i++) {
+ Future> result =
+ executor.submit(
+ (Callable)
+ () -> {
+ for (int j = 0; j < iterations; j++) {
+ requestAndCompleteRaceConditionIteration();
+ }
+ return null;
+ });
+ results.add(result);
+ }
+
+ executor.shutdown();
+
+ for (Future> result : results) {
+ try {
+ result.get();
+ } catch (ExecutionException e) {
+ throw e.getCause();
+ }
+ }
+ }
+
+ private static void requestAndCompleteRaceConditionIteration()
+ throws InterruptedException, ExecutionException {
+ MockStreamingApi.MockResponseObserver observer =
+ new MockStreamingApi.MockResponseObserver<>(false);
+ ReframingResponseObserver underTest =
+ new ReframingResponseObserver<>(
+ observer, new ReframingResponseObserverTest.DasherizingReframer(1));
+
+ // This is intentionally not a Phaser, the Phaser seems to drastically reduce the reproduction
+ // rate of the
+ // original race condition.
+ CountDownLatch readySignal = new CountDownLatch(2);
+ CompletableFuture startSignal = new CompletableFuture<>();
+
+ ExecutorService executor = Executors.newFixedThreadPool(2);
+
+ Future f1 =
+ executor.submit(
+ () -> {
+ // no setup, tell controller thread we are ready and wait for the start signal
+ readySignal.countDown();
+ startSignal.get();
+
+ // Race start
+ underTest.onComplete();
+ // Race end
+
+ return null;
+ });
+
+ Future f2 =
+ executor.submit(
+ () -> {
+ // Setup before race - simulate that the ServerStream iterator got one row and is now
+ // checking if there
+ // is another. This is the lead up to the race with grpc's onComplete
+ underTest.onStart(
+ new StreamController() {
+ @Override
+ public void cancel() {}
+
+ @Override
+ public void disableAutoInboundFlowControl() {}
+
+ @Override
+ public void request(int count) {}
+ });
+ observer.getController().request(1);
+ underTest.onResponse("moo");
+
+ // Setup complete, tell controller thread we are ready and wait for the start signal
+ readySignal.countDown();
+ startSignal.get();
+
+ // Race start
+ observer.getController().request(1);
+ // Race end
+
+ return null;
+ });
+ executor.shutdown();
+
+ // Wait for worker setup
+ readySignal.await();
+ // Tell workers to race
+ startSignal.complete(null);
+
+ // Wait workers to finish
+ f1.get();
+ f2.get();
+
+ // the outer observer should be told of the completion of rpc
+ assertWithMessage("outer observer should not hang").that(observer.isDone()).isTrue();
+ }
+
/**
* A simple implementation of a {@link Reframer}. The input string is split by dash, and the
* output is concatenated by dashes. The test can verify M:N behavior by adjusting the
diff --git a/grpc-google-cloud-bigtable-admin-v2/pom.xml b/grpc-google-cloud-bigtable-admin-v2/pom.xml
index 04d778a18bc0..d0cc40e554dd 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.23.3
+ 2.23.4
grpc-google-cloud-bigtable-admin-v2
GRPC library for grpc-google-cloud-bigtable-admin-v2
com.google.cloud
google-cloud-bigtable-parent
- 2.23.3
+ 2.23.4
@@ -18,14 +18,14 @@
com.google.cloud
google-cloud-bigtable-deps-bom
- 2.23.3
+ 2.23.4
pom
import
com.google.cloud
google-cloud-bigtable-bom
- 2.23.3
+ 2.23.4
pom
import
diff --git a/grpc-google-cloud-bigtable-v2/pom.xml b/grpc-google-cloud-bigtable-v2/pom.xml
index ed0d82873816..e9454f9d9c33 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.23.3
+ 2.23.4
grpc-google-cloud-bigtable-v2
GRPC library for grpc-google-cloud-bigtable-v2
com.google.cloud
google-cloud-bigtable-parent
- 2.23.3
+ 2.23.4
@@ -18,14 +18,14 @@
com.google.cloud
google-cloud-bigtable-deps-bom
- 2.23.3
+ 2.23.4
pom
import
com.google.cloud
google-cloud-bigtable-bom
- 2.23.3
+ 2.23.4
pom
import
diff --git a/pom.xml b/pom.xml
index 698ddd5b3d01..099ad6a7a932 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
google-cloud-bigtable-parent
pom
- 2.23.3
+ 2.23.4
Google Cloud Bigtable Parent
https://github.com/googleapis/java-bigtable
@@ -153,27 +153,27 @@
com.google.api.grpc
proto-google-cloud-bigtable-v2
- 2.23.3
+ 2.23.4
com.google.api.grpc
proto-google-cloud-bigtable-admin-v2
- 2.23.3
+ 2.23.4
com.google.api.grpc
grpc-google-cloud-bigtable-v2
- 2.23.3
+ 2.23.4
com.google.api.grpc
grpc-google-cloud-bigtable-admin-v2
- 2.23.3
+ 2.23.4
com.google.cloud
google-cloud-bigtable
- 2.23.3
+ 2.23.4
diff --git a/proto-google-cloud-bigtable-admin-v2/pom.xml b/proto-google-cloud-bigtable-admin-v2/pom.xml
index 89707484e997..1ce806c05215 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.23.3
+ 2.23.4
proto-google-cloud-bigtable-admin-v2
PROTO library for proto-google-cloud-bigtable-admin-v2
com.google.cloud
google-cloud-bigtable-parent
- 2.23.3
+ 2.23.4
@@ -18,14 +18,14 @@
com.google.cloud
google-cloud-bigtable-deps-bom
- 2.23.3
+ 2.23.4
pom
import
com.google.cloud
google-cloud-bigtable-bom
- 2.23.3
+ 2.23.4
pom
import
diff --git a/proto-google-cloud-bigtable-v2/pom.xml b/proto-google-cloud-bigtable-v2/pom.xml
index afb68d81cda3..3fc8a46a90bd 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.23.3
+ 2.23.4
proto-google-cloud-bigtable-v2
PROTO library for proto-google-cloud-bigtable-v2
com.google.cloud
google-cloud-bigtable-parent
- 2.23.3
+ 2.23.4
@@ -18,14 +18,14 @@
com.google.cloud
google-cloud-bigtable-deps-bom
- 2.23.3
+ 2.23.4
pom
import
com.google.cloud
google-cloud-bigtable-bom
- 2.23.3
+ 2.23.4
pom
import
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 6d15d3f59835..0a355270c6c0 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,7 +28,7 @@
com.google.cloud
google-cloud-bigtable
- 2.23.3
+ 2.23.4
diff --git a/test-proxy/pom.xml b/test-proxy/pom.xml
index bd08be820599..58a28cb061e6 100644
--- a/test-proxy/pom.xml
+++ b/test-proxy/pom.xml
@@ -12,11 +12,11 @@
google-cloud-bigtable-parent
com.google.cloud
- 2.23.3
+ 2.23.4
- 2.23.3
+ 2.23.4
diff --git a/versions.txt b/versions.txt
index 3a1d342605dc..92d8235d8843 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,10 +1,10 @@
# Format:
# module:released-version:current-version
-google-cloud-bigtable:2.23.3:2.23.3
-grpc-google-cloud-bigtable-admin-v2:2.23.3:2.23.3
-grpc-google-cloud-bigtable-v2:2.23.3:2.23.3
-proto-google-cloud-bigtable-admin-v2:2.23.3:2.23.3
-proto-google-cloud-bigtable-v2:2.23.3:2.23.3
-google-cloud-bigtable-emulator:0.160.3:0.160.3
-google-cloud-bigtable-emulator-core:2.23.3:2.23.3
+google-cloud-bigtable:2.23.4:2.23.4
+grpc-google-cloud-bigtable-admin-v2:2.23.4:2.23.4
+grpc-google-cloud-bigtable-v2:2.23.4:2.23.4
+proto-google-cloud-bigtable-admin-v2:2.23.4:2.23.4
+proto-google-cloud-bigtable-v2:2.23.4:2.23.4
+google-cloud-bigtable-emulator:0.160.4:0.160.4
+google-cloud-bigtable-emulator-core:2.23.4:2.23.4