Skip to content

Commit 1cea21c

Browse files
committed
feat: Add APIs to enable request priorities
1 parent fe4b6bc commit 1cea21c

File tree

7 files changed

+340
-1
lines changed

7 files changed

+340
-1
lines changed

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import com.google.api.core.InternalApi;
1919
import com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny;
20+
import com.google.bigtable.admin.v2.AppProfile.Priority;
21+
import com.google.bigtable.admin.v2.AppProfile.StandardIsolation;
2022
import com.google.bigtable.admin.v2.AppProfileName;
2123
import com.google.common.base.Objects;
2224
import com.google.common.base.Preconditions;
@@ -76,6 +78,15 @@ public RoutingPolicy getPolicy() {
7678
}
7779
}
7880

81+
public IsolationPolicy getIsolationPolicy() {
82+
if (proto.hasStandardIsolation()) {
83+
return new StandardIsolationPolicy(proto.getStandardIsolation());
84+
} else {
85+
// Should never happen because the constructor verifies that one must exist.
86+
throw new VerifyException();
87+
}
88+
}
89+
7990
/** Gets the id of this AppProfile. */
8091
@SuppressWarnings("WeakerAccess")
8192
public String getId() {
@@ -292,4 +303,108 @@ public int hashCode() {
292303
return Objects.hashCode(proto);
293304
}
294305
}
306+
307+
/** Represents the options for isolating this app profile's traffic from other use cases. */
308+
@SuppressWarnings("WeakerAccess")
309+
public interface IsolationPolicy {}
310+
311+
/**
312+
* The possible priorities for an app profile. Note that higher priority writes can sometimes
313+
* queue behind lower priority writes to the same tablet, as writes must be strictly sequenced in
314+
* the durability log.
315+
*/
316+
public static enum Priority {
317+
PRIORITY_LOW(com.google.bigtable.admin.v2.AppProfile.Priority.PRIORITY_LOW),
318+
PRIORITY_MEDIUM(com.google.bigtable.admin.v2.AppProfile.Priority.PRIORITY_MEDIUM),
319+
PRIORITY_HIGH(com.google.bigtable.admin.v2.AppProfile.Priority.PRIORITY_HIGH);
320+
321+
private final com.google.bigtable.admin.v2.AppProfile.Priority proto;
322+
323+
/**
324+
* Wraps the protobuf. This method is considered an internal implementation detail and not meant
325+
* to be used by applications.
326+
*/
327+
@InternalApi
328+
public static Priority fromProto(com.google.bigtable.admin.v2.AppProfile.Priority proto) {
329+
Preconditions.checkNotNull(proto);
330+
331+
for (Priority priority : values()) {
332+
if (priority.proto.equals(proto)) {
333+
return priority;
334+
}
335+
}
336+
337+
throw new IllegalArgumentException("Unknown priority: " + proto);
338+
}
339+
340+
Priority(com.google.bigtable.admin.v2.AppProfile.Priority proto) {
341+
this.proto = proto;
342+
}
343+
344+
/**
345+
* Creates the request protobuf. This method is considered an internal implementation detail and
346+
* not meant to be used by applications.
347+
*/
348+
@InternalApi
349+
public com.google.bigtable.admin.v2.AppProfile.Priority toProto() {
350+
return proto;
351+
}
352+
}
353+
354+
/**
355+
* A standard {@link IsolationPolicy} for isolating this app profile's traffic from other use
356+
* cases.
357+
*/
358+
public static class StandardIsolationPolicy implements IsolationPolicy {
359+
private final StandardIsolation proto;
360+
361+
/** Creates a new instance of {@link StandardIsolationPolicy}. */
362+
public static StandardIsolationPolicy of() {
363+
return new StandardIsolationPolicy(StandardIsolation.getDefaultInstance());
364+
}
365+
366+
/** Creates a new instance of {@link StandardIsolationPolicy} with the specified priority. */
367+
public static StandardIsolationPolicy of(Priority priority) {
368+
return new StandardIsolationPolicy(
369+
StandardIsolation.newBuilder().setPriority(priority.toProto()).build());
370+
}
371+
372+
/*
373+
* Returns the priority for this app profile.
374+
*/
375+
public Priority getPriority() {
376+
return Priority.fromProto(proto.getPriority());
377+
}
378+
379+
private StandardIsolationPolicy(
380+
com.google.bigtable.admin.v2.AppProfile.StandardIsolation proto) {
381+
this.proto = proto;
382+
}
383+
384+
/**
385+
* Creates the request protobuf. This method is considered an internal implementation detail and
386+
* not meant to be used by applications.
387+
*/
388+
@InternalApi
389+
com.google.bigtable.admin.v2.AppProfile.StandardIsolation toProto() {
390+
return proto;
391+
}
392+
393+
@Override
394+
public boolean equals(Object o) {
395+
if (this == o) {
396+
return true;
397+
}
398+
if (o == null || getClass() != o.getClass()) {
399+
return false;
400+
}
401+
StandardIsolationPolicy that = (StandardIsolationPolicy) o;
402+
return Objects.equal(proto, that.proto);
403+
}
404+
405+
@Override
406+
public int hashCode() {
407+
return Objects.hashCode(proto);
408+
}
409+
}
295410
}

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717

1818
import com.google.api.core.InternalApi;
1919
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
20+
import com.google.cloud.bigtable.admin.v2.models.AppProfile.IsolationPolicy;
2021
import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy;
2122
import com.google.cloud.bigtable.admin.v2.models.AppProfile.RoutingPolicy;
2223
import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy;
24+
import com.google.cloud.bigtable.admin.v2.models.AppProfile.StandardIsolationPolicy;
2325
import com.google.common.base.Preconditions;
2426
import javax.annotation.Nonnull;
2527

@@ -92,6 +94,21 @@ public CreateAppProfileRequest setRoutingPolicy(RoutingPolicy routingPolicy) {
9294
return this;
9395
}
9496

97+
/** Sets the isolation policy for all read/write requests that use this app profile. */
98+
public CreateAppProfileRequest setIsolationPolicy(IsolationPolicy isolationPolicy) {
99+
Preconditions.checkNotNull(isolationPolicy);
100+
101+
if (isolationPolicy instanceof StandardIsolationPolicy) {
102+
proto
103+
.getAppProfileBuilder()
104+
.setStandardIsolation(((StandardIsolationPolicy) isolationPolicy).toProto());
105+
} else {
106+
throw new IllegalArgumentException("Unknown policy type: " + isolationPolicy);
107+
}
108+
109+
return this;
110+
}
111+
95112
/**
96113
* Creates the request protobuf. This method is considered an internal implementation detail and
97114
* not meant to be used by applications.

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717

1818
import com.google.api.core.InternalApi;
1919
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
20+
import com.google.cloud.bigtable.admin.v2.models.AppProfile.IsolationPolicy;
2021
import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy;
2122
import com.google.cloud.bigtable.admin.v2.models.AppProfile.RoutingPolicy;
2223
import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy;
24+
import com.google.cloud.bigtable.admin.v2.models.AppProfile.StandardIsolationPolicy;
2325
import com.google.common.base.Objects;
2426
import com.google.common.base.Preconditions;
2527
import com.google.protobuf.FieldMask;
@@ -121,6 +123,22 @@ public UpdateAppProfileRequest setRoutingPolicy(@Nonnull RoutingPolicy routingPo
121123
return this;
122124
}
123125

126+
/** Sets the isolation policy for all read/write requests that use this app profile. */
127+
public UpdateAppProfileRequest setIsolationPolicy(@Nonnull IsolationPolicy isolationPolicy) {
128+
Preconditions.checkNotNull(isolationPolicy);
129+
130+
if (isolationPolicy instanceof StandardIsolationPolicy) {
131+
proto
132+
.getAppProfileBuilder()
133+
.setStandardIsolation(((StandardIsolationPolicy) isolationPolicy).toProto());
134+
updateFieldMask(com.google.bigtable.admin.v2.AppProfile.STANDARD_ISOLATION_FIELD_NUMBER);
135+
} else {
136+
throw new IllegalArgumentException("Unknown policy type: " + isolationPolicy);
137+
}
138+
139+
return this;
140+
}
141+
124142
private void updateFieldMask(int fieldNumber) {
125143
FieldMask newMask =
126144
FieldMaskUtil.fromFieldNumbers(com.google.bigtable.admin.v2.AppProfile.class, fieldNumber);

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTests.java

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
4444
import com.google.cloud.bigtable.admin.v2.models.AppProfile;
4545
import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy;
46+
import com.google.cloud.bigtable.admin.v2.models.AppProfile.Priority;
47+
import com.google.cloud.bigtable.admin.v2.models.AppProfile.StandardIsolationPolicy;
4648
import com.google.cloud.bigtable.admin.v2.models.Cluster;
4749
import com.google.cloud.bigtable.admin.v2.models.ClusterAutoscalingConfig;
4850
import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest;
@@ -82,7 +84,7 @@
8284

8385
@RunWith(JUnit4.class)
8486
/**
85-
* Tests for {@link BigtableTableAdminClient}. This test class uses Mockito so it has been
87+
* Tests for {@link BigtableInstanceAdminClient}. This test class uses Mockito so it has been
8688
* explicitly excluded from Native Image testing by not following the naming convention of (IT* and
8789
* *ClientTest).
8890
*/
@@ -983,6 +985,55 @@ public void testCreateAppProfileAddMultipleClusterIdsWithList() {
983985
assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse));
984986
}
985987

988+
@Test
989+
public void testCreateAppProfileAddPriority() {
990+
// Setup
991+
Mockito.when(mockStub.createAppProfileCallable()).thenReturn(mockCreateAppProfileCallable);
992+
993+
com.google.bigtable.admin.v2.CreateAppProfileRequest expectedRequest =
994+
com.google.bigtable.admin.v2.CreateAppProfileRequest.newBuilder()
995+
.setParent(NameUtil.formatInstanceName(PROJECT_ID, INSTANCE_ID))
996+
.setAppProfileId(APP_PROFILE_ID)
997+
.setAppProfile(
998+
com.google.bigtable.admin.v2.AppProfile.newBuilder()
999+
.setDescription("my description")
1000+
.setMultiClusterRoutingUseAny(
1001+
com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny
1002+
.newBuilder()
1003+
.addClusterIds("cluster-id-1"))
1004+
.setStandardIsolation(
1005+
com.google.bigtable.admin.v2.AppProfile.StandardIsolation.newBuilder()
1006+
.setPriority(
1007+
com.google.bigtable.admin.v2.AppProfile.Priority.PRIORITY_MEDIUM)))
1008+
.build();
1009+
1010+
com.google.bigtable.admin.v2.AppProfile expectedResponse =
1011+
com.google.bigtable.admin.v2.AppProfile.newBuilder()
1012+
.setName(APP_PROFILE_NAME)
1013+
.setDescription("my description")
1014+
.setMultiClusterRoutingUseAny(
1015+
com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny.newBuilder()
1016+
.addClusterIds("cluster-id-1"))
1017+
.setStandardIsolation(
1018+
com.google.bigtable.admin.v2.AppProfile.StandardIsolation.newBuilder()
1019+
.setPriority(com.google.bigtable.admin.v2.AppProfile.Priority.PRIORITY_MEDIUM))
1020+
.build();
1021+
1022+
Mockito.when(mockCreateAppProfileCallable.futureCall(expectedRequest))
1023+
.thenReturn(ApiFutures.immediateFuture(expectedResponse));
1024+
1025+
// Execute
1026+
AppProfile actualResult =
1027+
adminClient.createAppProfile(
1028+
CreateAppProfileRequest.of(INSTANCE_ID, APP_PROFILE_ID)
1029+
.setDescription("my description")
1030+
.setRoutingPolicy(MultiClusterRoutingPolicy.of("cluster-id-1"))
1031+
.setIsolationPolicy(StandardIsolationPolicy.of(Priority.PRIORITY_MEDIUM)));
1032+
1033+
// Verify
1034+
assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse));
1035+
}
1036+
9861037
@Test
9871038
public void testGetAppProfile() {
9881039
// Setup
@@ -1101,6 +1152,47 @@ public void testUpdateAppProfile() {
11011152
assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse));
11021153
}
11031154

1155+
@Test
1156+
public void testUpdateAppProfileStandardIsolation() {
1157+
// Setup
1158+
Mockito.when(mockStub.updateAppProfileOperationCallable())
1159+
.thenReturn(mockUpdateAppProfileCallable);
1160+
1161+
com.google.bigtable.admin.v2.UpdateAppProfileRequest expectedRequest =
1162+
com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder()
1163+
.setAppProfile(
1164+
com.google.bigtable.admin.v2.AppProfile.newBuilder()
1165+
.setName(APP_PROFILE_NAME)
1166+
.setStandardIsolation(
1167+
com.google.bigtable.admin.v2.AppProfile.StandardIsolation.newBuilder()
1168+
.setPriority(
1169+
com.google.bigtable.admin.v2.AppProfile.Priority.PRIORITY_LOW)))
1170+
.setUpdateMask(FieldMask.newBuilder().addPaths("standard_isolation"))
1171+
.build();
1172+
1173+
com.google.bigtable.admin.v2.AppProfile expectedResponse =
1174+
com.google.bigtable.admin.v2.AppProfile.newBuilder()
1175+
.setName(APP_PROFILE_NAME)
1176+
.setMultiClusterRoutingUseAny(
1177+
com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny
1178+
.getDefaultInstance())
1179+
.setStandardIsolation(
1180+
com.google.bigtable.admin.v2.AppProfile.StandardIsolation.newBuilder()
1181+
.setPriority(com.google.bigtable.admin.v2.AppProfile.Priority.PRIORITY_LOW))
1182+
.build();
1183+
1184+
mockOperationResult(mockUpdateAppProfileCallable, expectedRequest, expectedResponse);
1185+
1186+
// Execute
1187+
AppProfile actualResult =
1188+
adminClient.updateAppProfile(
1189+
UpdateAppProfileRequest.of(INSTANCE_ID, APP_PROFILE_ID)
1190+
.setIsolationPolicy(StandardIsolationPolicy.of(Priority.PRIORITY_LOW)));
1191+
1192+
// Verify
1193+
assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse));
1194+
}
1195+
11041196
@Test
11051197
public void testDeleteAppProfile() throws Exception {
11061198
// Setup

0 commit comments

Comments
 (0)