Skip to content

Commit 00f6d2d

Browse files
authored
feat: adding utility to transform protobuf into model object (#299)
* feat: adding utility to transform protobuf into model object With this commit, User shall be able to transform protobuf object to bigtable client's specific model objects. * chore: addressed feedback comments - updated the JavaDoc - marked the utility as `@BetaApi` * chore: addressed feedback comments - Rephrased Javadoc to include more explanation - change `Mutation#fromProto` visibility to package only * chore: removed VisibleForTesting annotation As Mutation#fromProto is being used by RowMutation#fromProto, So removed `@VisibleForTesting` annotation * chore: extended unit tests to verify project and instance override
1 parent bc215c5 commit 00f6d2d

File tree

10 files changed

+205
-0
lines changed

10 files changed

+205
-0
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.models;
1717

18+
import com.google.api.core.BetaApi;
1819
import com.google.api.core.InternalApi;
1920
import com.google.bigtable.v2.MutateRowsRequest;
2021
import com.google.cloud.bigtable.data.v2.internal.NameUtil;
@@ -114,6 +115,26 @@ public MutateRowsRequest toProto(RequestContext requestContext) {
114115
.build();
115116
}
116117

118+
/**
119+
* Wraps the protobuf {@link MutateRowsRequest}.
120+
*
121+
* <p>This is meant for advanced usage only. Please ensure that the MutateRowsRequest does not use
122+
* server side timestamps. The BigtableDataClient assumes that mutation present in BulkMutation
123+
* are idempotent and is configured to enable retries by default. If serverside timestamps are
124+
* enabled then that can lead to duplicate mutations.
125+
*
126+
* <p>WARNING: when applied, the resulting mutation object will ignore the project id and instance
127+
* id in the table_name and instead apply the configuration in the client.
128+
*/
129+
@BetaApi
130+
public static BulkMutation fromProto(@Nonnull MutateRowsRequest request) {
131+
BulkMutation bulkMutation =
132+
BulkMutation.create(NameUtil.extractTableIdFromTableName(request.getTableName()));
133+
bulkMutation.builder = request.toBuilder();
134+
135+
return bulkMutation;
136+
}
137+
117138
/** Creates a copy of {@link BulkMutation}. */
118139
@Override
119140
public BulkMutation clone() {

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.models;
1717

18+
import com.google.api.core.BetaApi;
1819
import com.google.api.core.InternalApi;
1920
import com.google.bigtable.v2.CheckAndMutateRowRequest;
2021
import com.google.cloud.bigtable.data.v2.internal.NameUtil;
@@ -136,4 +137,20 @@ public CheckAndMutateRowRequest toProto(RequestContext requestContext) {
136137
.setAppProfileId(requestContext.getAppProfileId())
137138
.build();
138139
}
140+
141+
/**
142+
* Wraps the protobuf {@link CheckAndMutateRowRequest}.
143+
*
144+
* <p>WARNING: Please note that the table_name will be overwritten by the configuration in the
145+
* BigtableDataClient.
146+
*/
147+
@BetaApi
148+
public static ConditionalRowMutation fromProto(@Nonnull CheckAndMutateRowRequest request) {
149+
String tableId = NameUtil.extractTableIdFromTableName(request.getTableName());
150+
ConditionalRowMutation rowMutation =
151+
ConditionalRowMutation.create(tableId, request.getRowKey());
152+
rowMutation.builder = request.toBuilder();
153+
154+
return rowMutation;
155+
}
139156
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ public static Mutation fromProtoUnsafe(List<com.google.bigtable.v2.Mutation> pro
8787
return mutation;
8888
}
8989

90+
/**
91+
* Constructs a row mutation from an existing protobuf object.
92+
*
93+
* <p>Callers must ensure that the protobuf argument is not using serverside timestamps. The
94+
* client assumes that all mutations are idempotent and will retry in case of transient errors.
95+
* This can lead to row duplication.
96+
*
97+
* <p>When applied, the resulting Mutation object will ignore the project id and instance id in
98+
* the table_name and instead apply the configuration in the client
99+
*/
100+
static Mutation fromProto(List<com.google.bigtable.v2.Mutation> protos) {
101+
Mutation mutation = new Mutation(false);
102+
mutation.mutations.addAll(protos);
103+
return mutation;
104+
}
105+
90106
private Mutation(boolean allowServersideTimestamp) {
91107
this.allowServersideTimestamp = allowServersideTimestamp;
92108
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.models;
1717

18+
import com.google.api.core.BetaApi;
1819
import com.google.api.core.InternalApi;
1920
import com.google.bigtable.v2.ReadModifyWriteRowRequest;
2021
import com.google.bigtable.v2.ReadModifyWriteRule;
@@ -137,4 +138,20 @@ public ReadModifyWriteRowRequest toProto(RequestContext requestContext) {
137138
.setAppProfileId(requestContext.getAppProfileId())
138139
.build();
139140
}
141+
142+
/**
143+
* Wraps the protobuf {@link ReadModifyWriteRowRequest}.
144+
*
145+
* <p>WARNING: Please note that the table_name will be overwritten by the configuration in the
146+
* BigtableDataClient.
147+
*/
148+
@BetaApi
149+
public static ReadModifyWriteRow fromProto(@Nonnull ReadModifyWriteRowRequest request) {
150+
String tableId = NameUtil.extractTableIdFromTableName(request.getTableName());
151+
152+
ReadModifyWriteRow row = ReadModifyWriteRow.create(tableId, request.getRowKey());
153+
row.builder = request.toBuilder();
154+
155+
return row;
156+
}
140157
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.models;
1717

18+
import com.google.api.core.BetaApi;
1819
import com.google.api.core.InternalApi;
1920
import com.google.bigtable.v2.MutateRowRequest;
2021
import com.google.bigtable.v2.MutateRowsRequest;
@@ -214,4 +215,23 @@ public MutateRowsRequest toBulkProto(RequestContext requestContext) {
214215
Entry.newBuilder().setRowKey(key).addAllMutations(mutation.getMutations()).build())
215216
.build();
216217
}
218+
219+
/**
220+
* Wraps the protobuf {@link MutateRowRequest}.
221+
*
222+
* <p>This is meant for advanced usage only. Please ensure that the MutateRowRequest does not use
223+
* server side timestamps. The BigtableDataClient assumes that RowMutations are idempotent and is
224+
* configured to enable retries by default. If serverside timestamps are enabled, this can lead to
225+
* duplicate mutations.
226+
*
227+
* <p>WARNING: when applied, the resulting mutation object will ignore the project id and instance
228+
* id in the table_name and instead apply the configuration in the client.
229+
*/
230+
@BetaApi
231+
public static RowMutation fromProto(@Nonnull MutateRowRequest request) {
232+
String tableId = NameUtil.extractTableIdFromTableName(request.getTableName());
233+
234+
return RowMutation.create(
235+
tableId, request.getRowKey(), Mutation.fromProto(request.getMutationsList()));
236+
}
217237
}

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/BulkMutationTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,29 @@ public void addRowMutationEntry() {
147147
bulkMutation.add(entry);
148148
assertThat(bulkMutation.toProto(REQUEST_CONTEXT).getEntriesList()).contains(entry.toProto());
149149
}
150+
151+
@Test
152+
public void fromProtoTest() {
153+
BulkMutation expected =
154+
BulkMutation.create(TABLE_ID)
155+
.add(
156+
"key",
157+
Mutation.create().setCell("fake-family", "fake-qualifier", 10_000L, "fake-value"));
158+
159+
MutateRowsRequest protoRequest = expected.toProto(REQUEST_CONTEXT);
160+
BulkMutation actualBulkMutation = BulkMutation.fromProto(protoRequest);
161+
162+
assertThat(actualBulkMutation.toProto(REQUEST_CONTEXT)).isEqualTo(protoRequest);
163+
164+
String projectId = "fresh-project";
165+
String instanceId = "fresh-instance";
166+
String appProfile = "fresh-app-profile";
167+
MutateRowsRequest overriddenRequest =
168+
actualBulkMutation.toProto(RequestContext.create(projectId, instanceId, appProfile));
169+
170+
assertThat(overriddenRequest).isNotEqualTo(protoRequest);
171+
assertThat(overriddenRequest.getTableName())
172+
.matches(NameUtil.formatTableName(projectId, instanceId, TABLE_ID));
173+
assertThat(overriddenRequest.getAppProfileId()).matches(appProfile);
174+
}
150175
}

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ConditionalRowMutationTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,29 @@ public void serializationTest() throws IOException, ClassNotFoundException {
162162
ConditionalRowMutation actual = (ConditionalRowMutation) ois.readObject();
163163
assertThat(actual.toProto(REQUEST_CONTEXT)).isEqualTo(expected.toProto(REQUEST_CONTEXT));
164164
}
165+
166+
@Test
167+
public void fromProtoTest() {
168+
ConditionalRowMutation mutation =
169+
ConditionalRowMutation.create(TABLE_ID, TEST_KEY)
170+
.condition(Filters.FILTERS.key().regex("test"))
171+
.then(Mutation.create().setCell("family1", "qualifier1", 10_000L, "value"))
172+
.otherwise(Mutation.create().deleteFamily("family"));
173+
174+
CheckAndMutateRowRequest protoRequest = mutation.toProto(REQUEST_CONTEXT);
175+
ConditionalRowMutation actualRequest = ConditionalRowMutation.fromProto(protoRequest);
176+
177+
assertThat(actualRequest.toProto(REQUEST_CONTEXT)).isEqualTo(protoRequest);
178+
179+
String projectId = "fresh-project";
180+
String instanceId = "fresh-instance";
181+
String appProfile = "fresh-app-profile";
182+
CheckAndMutateRowRequest overriddenRequest =
183+
actualRequest.toProto(RequestContext.create(projectId, instanceId, appProfile));
184+
185+
assertThat(overriddenRequest).isNotEqualTo(protoRequest);
186+
assertThat(overriddenRequest.getTableName())
187+
.matches(NameUtil.formatTableName(projectId, instanceId, TABLE_ID));
188+
assertThat(overriddenRequest.getAppProfileId()).matches(appProfile);
189+
}
165190
}

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/MutationTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,20 @@ public void testWithLongValue() {
254254
.setValue(ByteString.copyFrom(Longs.toByteArray(20_000L)))
255255
.build());
256256
}
257+
258+
@Test
259+
public void fromProtoTest() {
260+
mutation
261+
.setCell(
262+
"fake-family",
263+
ByteString.copyFromUtf8("fake-qualifier"),
264+
1_000,
265+
ByteString.copyFromUtf8("fake-value"))
266+
.deleteCells("fake-family", ByteString.copyFromUtf8("fake-qualifier"))
267+
.deleteFamily("fake-family2");
268+
269+
List<com.google.bigtable.v2.Mutation> protoMutation = mutation.getMutations();
270+
271+
assertThat(Mutation.fromProto(protoMutation).getMutations()).isEqualTo(protoMutation);
272+
}
257273
}

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/ReadModifyWriteRowTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,28 @@ public void serializationTest() throws IOException, ClassNotFoundException {
113113
ReadModifyWriteRow actual = (ReadModifyWriteRow) ois.readObject();
114114
assertThat(actual.toProto(REQUEST_CONTEXT)).isEqualTo(expected.toProto(REQUEST_CONTEXT));
115115
}
116+
117+
@Test
118+
public void fromProtoTest() {
119+
ReadModifyWriteRow expected =
120+
ReadModifyWriteRow.create(TABLE_ID, "row-key")
121+
.increment("fake-family", ByteString.copyFromUtf8("fake-qualifier"), 1)
122+
.append("fake-family", "fake-qualifier", "fake-value");
123+
124+
ReadModifyWriteRowRequest protoRequest = expected.toProto(REQUEST_CONTEXT);
125+
ReadModifyWriteRow actualRequest = ReadModifyWriteRow.fromProto(protoRequest);
126+
127+
assertThat(actualRequest.toProto(REQUEST_CONTEXT)).isEqualTo(protoRequest);
128+
129+
String projectId = "fresh-project";
130+
String instanceId = "fresh-instance";
131+
String appProfile = "fresh-app-profile";
132+
ReadModifyWriteRowRequest overriddenRequest =
133+
actualRequest.toProto(RequestContext.create(projectId, instanceId, appProfile));
134+
135+
assertThat(overriddenRequest).isNotEqualTo(protoRequest);
136+
assertThat(overriddenRequest.getTableName())
137+
.matches(NameUtil.formatTableName(projectId, instanceId, TABLE_ID));
138+
assertThat(overriddenRequest.getAppProfileId()).matches(appProfile);
139+
}
116140
}

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/models/RowMutationTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,28 @@ public void testWithLongValue() {
139139
.setValue(ByteString.copyFrom(Longs.toByteArray(100_000L)))
140140
.build());
141141
}
142+
143+
@Test
144+
public void fromProtoTest() {
145+
RowMutation rowMutation =
146+
RowMutation.create("fake-table", "fake-key")
147+
.setCell("fake-family", "fake-qualifier-1", "fake-value")
148+
.setCell("fake-family", "fake-qualifier-2", 30_000L, "fake-value-2");
149+
150+
MutateRowRequest protoRequest = rowMutation.toProto(REQUEST_CONTEXT);
151+
RowMutation actualRequest = RowMutation.fromProto(protoRequest);
152+
153+
assertThat(actualRequest.toProto(REQUEST_CONTEXT)).isEqualTo(protoRequest);
154+
155+
String projectId = "fresh-project";
156+
String instanceId = "fresh-instance";
157+
String appProfile = "fresh-app-profile";
158+
MutateRowRequest overriddenRequest =
159+
actualRequest.toProto(RequestContext.create(projectId, instanceId, appProfile));
160+
161+
assertThat(overriddenRequest).isNotEqualTo(protoRequest);
162+
assertThat(overriddenRequest.getTableName())
163+
.matches(NameUtil.formatTableName(projectId, instanceId, TABLE_ID));
164+
assertThat(overriddenRequest.getAppProfileId()).matches(appProfile);
165+
}
142166
}

0 commit comments

Comments
 (0)