Skip to content

Commit 55b65cc

Browse files
igorbernstein2garrettjonesgoogle
authored andcommitted
Bigtable: 04. Surface: MutateRow (#2861)
1 parent 13c8334 commit 55b65cc

12 files changed

Lines changed: 875 additions & 25 deletions

File tree

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.google.cloud.bigtable.data.v2.wrappers.Query;
2828
import com.google.cloud.bigtable.data.v2.wrappers.Row;
2929
import com.google.cloud.bigtable.data.v2.wrappers.RowAdapter;
30+
import com.google.cloud.bigtable.data.v2.wrappers.RowMutation;
3031
import java.io.IOException;
3132
import java.util.List;
3233

@@ -292,6 +293,46 @@ public UnaryCallable<String, List<KeyOffset>> sampleRowKeysCallable() {
292293
return stub.sampleRowKeysCallable();
293294
}
294295

296+
/**
297+
* Convenience method to asynchronously mutate a single row atomically. Cells already present in
298+
* the row are left unchanged unless explicitly changed by the {@link RowMutation}.
299+
*
300+
* <p>Sample code:
301+
*
302+
* <pre>{@code
303+
* InstanceName instanceName = InstanceName.of("[PROJECT]", "[INSTANCE]");
304+
* try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) {
305+
* RowMutation mutation = RowMutation.create("[TABLE]", "[ROW KEY]")
306+
* .setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]");
307+
*
308+
* ApitFuture<Void> future = bigtableClient.mutateRow(mutation);
309+
* }
310+
* }</pre>
311+
*/
312+
public ApiFuture<Void> mutateRow(RowMutation rowMutation) {
313+
return mutateRowCallable().futureCall(rowMutation);
314+
}
315+
316+
/**
317+
* Mutates a single row atomically. Cells already present in the row are left unchanged unless
318+
* explicitly changed by the {@link RowMutation}.
319+
*
320+
* <p>Sample code:
321+
*
322+
* <pre>{@code
323+
* InstanceName instanceName = InstanceName.of("[PROJECT]", "[INSTANCE]");
324+
* try (BigtableClient bigtableClient = BigtableClient.create(instanceName)) {
325+
* RowMutation mutation = RowMutation.create("[TABLE]", "[ROW KEY]")
326+
* .setCell("[FAMILY NAME]", "[QUALIFIER]", "[VALUE]");
327+
*
328+
* bigtableClient.mutateRowCallable().call(mutation);
329+
* }
330+
* }</pre>
331+
*/
332+
public UnaryCallable<RowMutation, Void> mutateRowCallable() {
333+
return stub.mutateRowCallable();
334+
}
335+
295336
/** Close the clients and releases all associated resources. */
296337
@Override
297338
public void close() throws Exception {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.google.cloud.bigtable.data.v2.wrappers.KeyOffset;
2424
import com.google.cloud.bigtable.data.v2.wrappers.Query;
2525
import com.google.cloud.bigtable.data.v2.wrappers.Row;
26+
import com.google.cloud.bigtable.data.v2.wrappers.RowMutation;
2627
import java.io.IOException;
2728
import java.util.List;
2829
import javax.annotation.Nonnull;
@@ -83,6 +84,11 @@ public UnaryCallSettings<String, List<KeyOffset>> sampleRowKeysSettings() {
8384
return getTypedStubSettings().sampleRowKeysSettings();
8485
}
8586

87+
/** Returns the object with the settings used for calls to MutateRow. */
88+
public UnaryCallSettings<RowMutation, Void> mutateRowSettings() {
89+
return getTypedStubSettings().mutateRowSettings();
90+
}
91+
8692
@SuppressWarnings("unchecked")
8793
EnhancedBigtableStubSettings getTypedStubSettings() {
8894
return (EnhancedBigtableStubSettings) getStubSettings();
@@ -153,6 +159,11 @@ public UnaryCallSettings.Builder<String, List<KeyOffset>> sampleRowKeysSettings(
153159
return getTypedStubSettings().sampleRowKeysSettings();
154160
}
155161

162+
/** Returns the builder for the settings used for calls to MutateRow. */
163+
public UnaryCallSettings.Builder<RowMutation, Void> mutateRowSettings() {
164+
return getTypedStubSettings().mutateRowSettings();
165+
}
166+
156167
@SuppressWarnings("unchecked")
157168
private EnhancedBigtableStubSettings.Builder getTypedStubSettings() {
158169
return (EnhancedBigtableStubSettings.Builder) getStubSettings();

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.cloud.bigtable.data.v2.wrappers.Query;
2929
import com.google.cloud.bigtable.data.v2.wrappers.Row;
3030
import com.google.cloud.bigtable.data.v2.wrappers.RowAdapter;
31+
import com.google.cloud.bigtable.data.v2.wrappers.RowMutation;
3132
import java.io.IOException;
3233
import java.util.List;
3334

@@ -52,6 +53,7 @@ public class EnhancedBigtableStub implements AutoCloseable {
5253

5354
private final ServerStreamingCallable<Query, Row> readRowsCallable;
5455
private final UnaryCallable<String, List<KeyOffset>> sampleRowKeysCallable;
56+
private final UnaryCallable<RowMutation, Void> mutateRowCallable;
5557

5658
public static EnhancedBigtableStub create(EnhancedBigtableStubSettings settings)
5759
throws IOException {
@@ -80,6 +82,7 @@ public static EnhancedBigtableStub create(EnhancedBigtableStubSettings settings)
8082

8183
readRowsCallable = createReadRowsCallable(new DefaultRowAdapter());
8284
sampleRowKeysCallable = createSampleRowKeysCallable();
85+
mutateRowCallable = createMutateRowCallable();
8386
}
8487

8588
// <editor-fold desc="Callable creators">
@@ -113,6 +116,15 @@ public ApiFuture<List<KeyOffset>> futureCall(String request, ApiCallContext cont
113116
}
114117
};
115118
}
119+
120+
private UnaryCallable<RowMutation, Void> createMutateRowCallable() {
121+
return new UnaryCallable<RowMutation, Void>() {
122+
@Override
123+
public ApiFuture<Void> futureCall(RowMutation request, ApiCallContext context) {
124+
throw new UnsupportedOperationException("todo");
125+
}
126+
};
127+
}
116128
// </editor-fold>
117129

118130
// <editor-fold desc="Callable accessors">
@@ -123,6 +135,10 @@ public ServerStreamingCallable<Query, Row> readRowsCallable() {
123135
public UnaryCallable<String, List<KeyOffset>> sampleRowKeysCallable() {
124136
return sampleRowKeysCallable;
125137
}
138+
139+
public UnaryCallable<RowMutation, Void> mutateRowCallable() {
140+
return mutateRowCallable;
141+
}
126142
// </editor-fold>
127143

128144
@Override

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

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
import com.google.cloud.bigtable.data.v2.wrappers.KeyOffset;
2727
import com.google.cloud.bigtable.data.v2.wrappers.Query;
2828
import com.google.cloud.bigtable.data.v2.wrappers.Row;
29+
import com.google.cloud.bigtable.data.v2.wrappers.RowMutation;
2930
import com.google.common.base.Preconditions;
31+
import com.google.common.collect.ImmutableSet;
3032
import java.util.List;
33+
import java.util.Set;
3134
import javax.annotation.Nonnull;
3235
import org.threeten.bp.Duration;
3336

@@ -67,11 +70,27 @@ public class EnhancedBigtableStubSettings extends StubSettings<EnhancedBigtableS
6770
private static final int MAX_MESSAGE_SIZE = 256 * 1024 * 1024;
6871
private static final String SERVER_DEFAULT_APP_PROFILE_ID = "";
6972

73+
private static final Set<Code> DEFAULT_RETRY_CODES =
74+
ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE, Code.ABORTED);
75+
76+
private static final RetrySettings DEFAULT_RETRY_SETTINGS =
77+
RetrySettings.newBuilder()
78+
.setMaxAttempts(10)
79+
.setTotalTimeout(Duration.ofHours(1))
80+
.setInitialRetryDelay(Duration.ofMillis(100))
81+
.setRetryDelayMultiplier(1.3)
82+
.setMaxRetryDelay(Duration.ofMinutes(1))
83+
.setInitialRpcTimeout(Duration.ofSeconds(20))
84+
.setRpcTimeoutMultiplier(1)
85+
.setMaxRpcTimeout(Duration.ofSeconds(20))
86+
.build();
87+
7088
private final InstanceName instanceName;
7189
private final String appProfileId;
7290

7391
private final ServerStreamingCallSettings<Query, Row> readRowsSettings;
7492
private final UnaryCallSettings<String, List<KeyOffset>> sampleRowKeysSettings;
93+
private final UnaryCallSettings<RowMutation, Void> mutateRowSettings;
7594

7695
private EnhancedBigtableStubSettings(Builder builder) {
7796
super(builder);
@@ -81,6 +100,7 @@ private EnhancedBigtableStubSettings(Builder builder) {
81100
// Per method settings.
82101
readRowsSettings = builder.readRowsSettings.build();
83102
sampleRowKeysSettings = builder.sampleRowKeysSettings.build();
103+
mutateRowSettings = builder.mutateRowSettings.build();
84104
}
85105

86106
/** Create a new builder. */
@@ -108,6 +128,11 @@ public UnaryCallSettings<String, List<KeyOffset>> sampleRowKeysSettings() {
108128
return sampleRowKeysSettings;
109129
}
110130

131+
/** Returns the object with the settings used for calls to MutateRow. */
132+
public UnaryCallSettings<RowMutation, Void> mutateRowSettings() {
133+
return mutateRowSettings;
134+
}
135+
111136
/** Returns a builder containing all the values of this settings class. */
112137
public Builder toBuilder() {
113138
return new Builder(this);
@@ -120,6 +145,7 @@ public static class Builder extends StubSettings.Builder<EnhancedBigtableStubSet
120145

121146
private final ServerStreamingCallSettings.Builder<Query, Row> readRowsSettings;
122147
private final UnaryCallSettings.Builder<String, List<KeyOffset>> sampleRowKeysSettings;
148+
private final UnaryCallSettings.Builder<RowMutation, Void> mutateRowSettings;
123149

124150
/**
125151
* Initializes a new Builder with sane defaults for all settings.
@@ -148,36 +174,25 @@ private Builder() {
148174
readRowsSettings = ServerStreamingCallSettings.newBuilder();
149175
/* TODO: copy timeouts, retryCodes & retrySettings from baseSettings.readRows once it exists in GAPIC */
150176
readRowsSettings
151-
.setRetryableCodes(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE, Code.ABORTED)
177+
.setRetryableCodes(DEFAULT_RETRY_CODES)
178+
.setRetrySettings(DEFAULT_RETRY_SETTINGS)
152179
.setTimeoutCheckInterval(Duration.ofSeconds(10))
153-
.setIdleTimeout(Duration.ofMinutes(5))
154-
.setRetrySettings(
155-
RetrySettings.newBuilder()
156-
.setMaxAttempts(10)
157-
.setTotalTimeout(Duration.ofHours(1))
158-
.setInitialRetryDelay(Duration.ofMillis(100))
159-
.setRetryDelayMultiplier(1.3)
160-
.setMaxRetryDelay(Duration.ofMinutes(1))
161-
.setInitialRpcTimeout(Duration.ofSeconds(20))
162-
.setRpcTimeoutMultiplier(1)
163-
.setMaxRpcTimeout(Duration.ofSeconds(20))
164-
.build());
180+
.setIdleTimeout(Duration.ofMinutes(5));
165181

166182
sampleRowKeysSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
167183
/* TODO: copy retryCodes & retrySettings from baseSettings.sampleRowKeysSettings once it exists in GAPIC */
168184
sampleRowKeysSettings
169185
.setRetryableCodes(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE, Code.ABORTED)
170-
.setRetrySettings(
171-
RetrySettings.newBuilder()
172-
.setMaxAttempts(10)
173-
.setTotalTimeout(Duration.ofMinutes(1))
174-
.setInitialRetryDelay(Duration.ofMillis(100))
175-
.setRetryDelayMultiplier(1.3)
176-
.setMaxRetryDelay(Duration.ofMinutes(1))
177-
.setInitialRpcTimeout(Duration.ofSeconds(20))
178-
.setRpcTimeoutMultiplier(1)
179-
.setMaxRpcTimeout(Duration.ofSeconds(20))
180-
.build());
186+
.setRetrySettings(DEFAULT_RETRY_SETTINGS);
187+
188+
// NOTE: This client enforces client side timestamps, which makes all mutations retryable.
189+
// However, since the base GAPIC client allows for server side timestamps, it is not
190+
// configured to enable retries. So the retry settings have to be defined here instead of
191+
// being copied from the BigtableStubSettings.
192+
mutateRowSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
193+
mutateRowSettings
194+
.setRetryableCodes(DEFAULT_RETRY_CODES)
195+
.setRetrySettings(DEFAULT_RETRY_SETTINGS);
181196
}
182197

183198
private Builder(EnhancedBigtableStubSettings settings) {
@@ -188,6 +203,7 @@ private Builder(EnhancedBigtableStubSettings settings) {
188203
// Per method settings.
189204
readRowsSettings = settings.readRowsSettings.toBuilder();
190205
sampleRowKeysSettings = settings.sampleRowKeysSettings.toBuilder();
206+
mutateRowSettings = settings.mutateRowSettings.toBuilder();
191207
}
192208

193209
// <editor-fold desc="Private Helpers">
@@ -245,6 +261,11 @@ public UnaryCallSettings.Builder<String, List<KeyOffset>> sampleRowKeysSettings(
245261
return sampleRowKeysSettings;
246262
}
247263

264+
/** Returns the builder for the settings used for calls to MutateRow. */
265+
public UnaryCallSettings.Builder<RowMutation, Void> mutateRowSettings() {
266+
return mutateRowSettings;
267+
}
268+
248269
@SuppressWarnings("unchecked")
249270
public EnhancedBigtableStubSettings build() {
250271
Preconditions.checkState(instanceName != null, "InstanceName must be set");

0 commit comments

Comments
 (0)