Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit c85c3ba

Browse files
feat: add new session based protocol stack
The new protocol changes the paradigm of bigtable service from an RPC server where each operation is independent to more of a file like model where a table is opened and allows many read & write operations. This will have a significant impact on lowering latencies. All of the changes are internal to the client and the existing public surface remains the same. By default the new protocol is disabled and will be slowly enabled in the future using the client config api. Change-Id: I92db1ec5929019a06b1490b06ed0fd85893696c4
1 parent 05d2e48 commit c85c3ba

169 files changed

Lines changed: 17724 additions & 248 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

google-cloud-bigtable/pom.xml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,9 @@
159159
<artifactId>google-http-client-gson</artifactId>
160160
<scope>runtime</scope>
161161
</dependency>
162-
<!--
163-
grpc-stub is needed directly by our tests and transitively by grpc-alts at runtime.
164-
So it has to be declared as a direct dependency and to avoid overriding grpc-alts'
165-
runtime requirement it has to be promoted to the runtime scope.
166-
-->
167162
<dependency>
168163
<groupId>io.grpc</groupId>
169164
<artifactId>grpc-stub</artifactId>
170-
<scope>runtime</scope>
171165
</dependency>
172166
<dependency>
173167
<groupId>io.grpc</groupId>
@@ -217,6 +211,10 @@
217211
<groupId>io.opentelemetry</groupId>
218212
<artifactId>opentelemetry-api</artifactId>
219213
</dependency>
214+
<dependency>
215+
<groupId>io.opentelemetry</groupId>
216+
<artifactId>opentelemetry-context</artifactId>
217+
</dependency>
220218
<dependency>
221219
<groupId>io.opentelemetry</groupId>
222220
<artifactId>opentelemetry-sdk</artifactId>

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ public final class BigtableDataClientFactory implements AutoCloseable {
7474
*/
7575
public static BigtableDataClientFactory create(BigtableDataSettings defaultSettings)
7676
throws IOException {
77+
BigtableDataSettings.Builder builder = defaultSettings.toBuilder();
78+
builder.stubSettings().setSessionsEnabled(false);
79+
defaultSettings = builder.build();
80+
7781
BigtableClientContext sharedClientContext =
7882
BigtableClientContext.create(defaultSettings.getStubSettings());
7983
ClientOperationSettings perOpSettings = defaultSettings.getStubSettings().getPerOpSettings();

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataSettings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public static Builder newBuilderForEmulator(String hostname, int port) {
133133
.setMetricsProvider(
134134
NoopMetricsProvider.INSTANCE) // disable exporting metrics for emulator
135135
.disableInternalMetrics()
136+
.setSessionsEnabled(false)
136137
.setTransportChannelProvider(
137138
InstantiatingGrpcChannelProvider.newBuilder()
138139
.setMaxInboundMessageSize(256 * 1024 * 1024)
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigtable.data.v2.internal.api;
17+
18+
import com.google.bigtable.v2.FeatureFlags;
19+
import com.google.bigtable.v2.OpenAuthorizedViewRequest;
20+
import com.google.bigtable.v2.OpenAuthorizedViewRequest.Permission;
21+
import com.google.bigtable.v2.SessionMutateRowRequest;
22+
import com.google.bigtable.v2.SessionMutateRowResponse;
23+
import com.google.bigtable.v2.SessionReadRowRequest;
24+
import com.google.bigtable.v2.SessionReadRowResponse;
25+
import com.google.cloud.bigtable.data.v2.internal.channels.ChannelPool;
26+
import com.google.cloud.bigtable.data.v2.internal.csm.Metrics;
27+
import com.google.cloud.bigtable.data.v2.internal.csm.attributes.ClientInfo;
28+
import com.google.cloud.bigtable.data.v2.internal.session.SessionPool;
29+
import com.google.cloud.bigtable.data.v2.internal.session.VRpcDescriptor;
30+
import com.google.cloud.bigtable.data.v2.internal.util.ClientConfigurationManager;
31+
import io.grpc.CallOptions;
32+
import io.grpc.Deadline;
33+
import java.io.Closeable;
34+
import java.util.concurrent.CompletableFuture;
35+
import java.util.concurrent.ScheduledExecutorService;
36+
37+
public class AuthorizedViewAsync implements AutoCloseable, Closeable {
38+
39+
private final TableBase base;
40+
41+
static AuthorizedViewAsync createAndStart(
42+
FeatureFlags featureFlags,
43+
ClientInfo clientInfo,
44+
ClientConfigurationManager configManager,
45+
ChannelPool channelPool,
46+
CallOptions callOptions,
47+
String tableId,
48+
String viewId,
49+
Permission permission,
50+
Metrics metrics,
51+
ScheduledExecutorService executorService) {
52+
53+
AuthorizedViewName viewName =
54+
AuthorizedViewName.builder()
55+
.setProjectId(clientInfo.getInstanceName().getProjectId())
56+
.setInstanceId(clientInfo.getInstanceName().getInstanceId())
57+
.setTableId(tableId)
58+
.setAuthorizedViewId(viewId)
59+
.build();
60+
61+
OpenAuthorizedViewRequest openRequest =
62+
OpenAuthorizedViewRequest.newBuilder()
63+
.setAuthorizedViewName(viewName.toString())
64+
.setAppProfileId(clientInfo.getAppProfileId())
65+
.setPermission(permission)
66+
.build();
67+
68+
TableBase base =
69+
TableBase.createAndStart(
70+
openRequest,
71+
VRpcDescriptor.AUTHORIZED_VIEW_SESSION,
72+
VRpcDescriptor.READ_ROW_AUTH_VIEW,
73+
VRpcDescriptor.MUTATE_ROW_AUTH_VIEW,
74+
featureFlags,
75+
clientInfo,
76+
configManager,
77+
channelPool,
78+
callOptions,
79+
viewName.toString(),
80+
metrics,
81+
executorService);
82+
83+
return new AuthorizedViewAsync(base);
84+
}
85+
86+
AuthorizedViewAsync(TableBase viewBase) {
87+
this.base = viewBase;
88+
}
89+
90+
public SessionPool<?> getSessionPool() {
91+
return base.getSessionPool();
92+
}
93+
94+
public CompletableFuture<SessionReadRowResponse> readRow(
95+
SessionReadRowRequest req, Deadline deadline) {
96+
UnaryResponseFuture<SessionReadRowResponse> f = new UnaryResponseFuture<>();
97+
base.readRow(req, f, deadline);
98+
return f;
99+
}
100+
101+
public CompletableFuture<SessionMutateRowResponse> mutateRow(
102+
SessionMutateRowRequest req, Deadline deadline) {
103+
UnaryResponseFuture<SessionMutateRowResponse> f = new UnaryResponseFuture<>();
104+
base.mutateRow(req, f, deadline);
105+
return f;
106+
}
107+
108+
@Override
109+
public void close() {
110+
this.base.close();
111+
}
112+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.bigtable.data.v2.internal.api;
17+
18+
import com.google.auto.value.AutoValue;
19+
import com.google.common.base.Preconditions;
20+
import com.google.common.base.Splitter;
21+
import java.util.List;
22+
23+
@AutoValue
24+
public abstract class AuthorizedViewName {
25+
26+
public abstract String getProjectId();
27+
28+
public abstract String getInstanceId();
29+
30+
public abstract String getTableId();
31+
32+
public abstract String getAuthorizedViewId();
33+
34+
public InstanceName getInstanceName() {
35+
return InstanceName.builder()
36+
.setProjectId(getProjectId())
37+
.setInstanceId(getInstanceId())
38+
.build();
39+
}
40+
41+
public TableName getTableName() {
42+
return TableName.builder()
43+
.setProjectId(getProjectId())
44+
.setInstanceId(getInstanceId())
45+
.setTableId(getTableId())
46+
.build();
47+
}
48+
49+
@Override
50+
public final String toString() {
51+
return String.format("%s/authorizedViews/%s", getTableName(), getAuthorizedViewId());
52+
}
53+
54+
public static AuthorizedViewName of(
55+
String projectId, String instanceId, String tableId, String viewId) {
56+
return builder()
57+
.setProjectId(projectId)
58+
.setInstanceId(instanceId)
59+
.setTableId(tableId)
60+
.setAuthorizedViewId(viewId)
61+
.build();
62+
}
63+
64+
public static Builder builder() {
65+
return new AutoValue_AuthorizedViewName.Builder();
66+
}
67+
68+
public static AuthorizedViewName parse(String name) {
69+
List<String> parts = Splitter.on('/').splitToList(name);
70+
Preconditions.checkArgument(parts.size() == 8, "Invalid authorized view name: %s", name);
71+
Preconditions.checkArgument(
72+
"projects".equals(parts.get(0)),
73+
"Invalid authorized view name: %s, must start with projects/",
74+
name);
75+
Preconditions.checkArgument(
76+
!parts.get(1).isEmpty(), "Invalid authorized view name %s, must have a project id", name);
77+
Preconditions.checkArgument(
78+
"instances".equals(parts.get(2)),
79+
"Invalid authorized view name: %s, must start with projects/$PROJECT_ID/instances/",
80+
name);
81+
Preconditions.checkArgument(
82+
!parts.get(3).isEmpty(), "Invalid authorized view name %s, must have an instance id", name);
83+
Preconditions.checkArgument(
84+
"tables".equals(parts.get(4)),
85+
"Invalid authorized view name: %s, must start with projects/$PROJECT_ID/instances/$INSTANCE_ID/tables",
86+
name);
87+
Preconditions.checkArgument(
88+
!parts.get(5).isEmpty(), "Invalid authorized view name %s, must have table id", name);
89+
Preconditions.checkArgument(
90+
"authorizedViews".equals(parts.get(6)),
91+
"Invalid authorized view name: %s, must start with projects/$PROJECT_ID/instances/$INSTANCE_ID/tables/$TABLE_ID/authorizedViews",
92+
name);
93+
Preconditions.checkArgument(
94+
!parts.get(7).isEmpty(),
95+
"Invalid authorized view name %s, must have authorized view id",
96+
name);
97+
98+
return builder()
99+
.setProjectId(parts.get(1))
100+
.setInstanceId(parts.get(3))
101+
.setTableId(parts.get(5))
102+
.setAuthorizedViewId(parts.get(7))
103+
.build();
104+
}
105+
106+
@AutoValue.Builder
107+
public abstract static class Builder {
108+
public abstract Builder setProjectId(String projectId);
109+
110+
public abstract Builder setInstanceId(String instanceId);
111+
112+
public abstract Builder setTableId(String tableId);
113+
114+
public abstract Builder setAuthorizedViewId(String viewId);
115+
116+
public abstract AuthorizedViewName build();
117+
}
118+
}

0 commit comments

Comments
 (0)