Skip to content

Commit b32ff78

Browse files
chore: configure gRPC session streams with DirectExecutor
CallOptions.withExecutor(MoreExecutors.directExecutor()) on the session stream so Netty I/O threads deliver SessionStream.Listener callbacks directly; sessionSyncContext immediately trampolines off them.
1 parent fc9aafd commit b32ff78

3 files changed

Lines changed: 18 additions & 2 deletions

File tree

java-bigtable/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/channels/ChannelPoolDpImpl.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.common.base.Ticker;
2727
import com.google.common.collect.HashMultiset;
2828
import com.google.common.collect.Multiset;
29+
import com.google.common.util.concurrent.MoreExecutors;
2930
import io.grpc.CallOptions;
3031
import io.grpc.ClientCall;
3132
import io.grpc.ManagedChannel;
@@ -246,8 +247,11 @@ public synchronized SessionStream newStream(
246247
channelWrapper.group.numStreams++;
247248
totalStreams++;
248249

250+
// DirectExecutor: gRPC/Netty delivers SessionStream.Listener callbacks directly on the
251+
// I/O thread. All work must be fast and non-blocking; blocking work goes to sessionSyncContext.
249252
ClientCall<SessionRequest, SessionResponse> innerCall =
250-
channelWrapper.channel.newCall(desc, callOptions);
253+
channelWrapper.channel.newCall(
254+
desc, callOptions.withExecutor(MoreExecutors.directExecutor()));
251255

252256
return new SessionStreamImpl(innerCall) {
253257
// mark as null so that onClose can tell if onBeforeSessionStart was never called

java-bigtable/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/channels/SessionStream.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ public interface SessionStream {
3737

3838
public void forceClose(@Nullable String message, @Nullable Throwable cause);
3939

40+
/**
41+
* Callbacks for session stream events.
42+
*
43+
* <p><b>Invariant:</b> callbacks are delivered on Netty I/O threads via {@code DirectExecutor}.
44+
* All work must be fast and non-blocking — any user-facing or potentially blocking work must be
45+
* dispatched onto the session {@code SynchronizationContext} (which then forwards to the op
46+
* executor) before returning. Violating this stalls the channel.
47+
*/
4048
public interface Listener {
4149
void onBeforeSessionStart(PeerInfo peerInfo);
4250

java-bigtable/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/internal/channels/SingleChannelPool.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.google.bigtable.v2.SessionClientConfiguration.ChannelPoolConfiguration;
2020
import com.google.bigtable.v2.SessionRequest;
2121
import com.google.bigtable.v2.SessionResponse;
22+
import com.google.common.util.concurrent.MoreExecutors;
2223
import io.grpc.CallOptions;
2324
import io.grpc.ManagedChannel;
2425
import io.grpc.MethodDescriptor;
@@ -45,7 +46,10 @@ public void close() {
4546
@Override
4647
public SessionStream newStream(
4748
MethodDescriptor<SessionRequest, SessionResponse> desc, CallOptions callOptions) {
48-
return new SessionStreamImpl(channel.newCall(desc, callOptions));
49+
// DirectExecutor: gRPC/Netty delivers SessionStream.Listener callbacks directly on the
50+
// I/O thread. All work must be fast and non-blocking; blocking work goes to sessionSyncContext.
51+
return new SessionStreamImpl(
52+
channel.newCall(desc, callOptions.withExecutor(MoreExecutors.directExecutor())));
4953
}
5054

5155
@Override

0 commit comments

Comments
 (0)