Skip to content

Commit 8bcc89b

Browse files
Bigtable: clean up consistency token (#3570)
1 parent 427b155 commit 8bcc89b

File tree

5 files changed

+78
-82
lines changed

5 files changed

+78
-82
lines changed

google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ public ConsistencyToken generateConsistencyToken(String tableId) {
465465
* }
466466
* }</pre>
467467
*/
468-
public ApiFuture<ConsistencyToken> generateConsistencyTokenAsync(String tableId) {
468+
public ApiFuture<ConsistencyToken> generateConsistencyTokenAsync(final String tableId) {
469469
ApiFuture<GenerateConsistencyTokenResponse> tokenResp =
470470
this.stub
471471
.generateConsistencyTokenCallable()
@@ -475,8 +475,9 @@ public ApiFuture<ConsistencyToken> generateConsistencyTokenAsync(String tableId)
475475
tokenResp,
476476
new ApiFunction<GenerateConsistencyTokenResponse, ConsistencyToken>() {
477477
@Override
478-
public ConsistencyToken apply(GenerateConsistencyTokenResponse input) {
479-
return ConsistencyToken.fromProto(input);
478+
public ConsistencyToken apply(GenerateConsistencyTokenResponse proto) {
479+
TableName tableName = TableName.of(instanceName.getProject(), instanceName.getInstance(), tableId);
480+
return ConsistencyToken.of(tableName, proto.getConsistencyToken());
480481
}
481482
},
482483
MoreExecutors.directExecutor());
@@ -489,28 +490,25 @@ public ConsistencyToken apply(GenerateConsistencyTokenResponse input) {
489490
*
490491
* <pre>{@code
491492
* try(BigtableTableAdminClient client = BigtableTableAdminClient.create(InstanceName.of("[PROJECT]", "[INSTANCE]"))) {
492-
* boolean consistent = client.isConsistent("tableId", token);
493-
* }
494-
* }</pre>
495-
*/
496-
public boolean isConsistent(String tableId, ConsistencyToken token) {
497-
return awaitFuture(isConsistentAsync(tableId, token));
498-
}
499-
500-
/**
501-
* Checks replication consistency for the specified token consistency token asynchronously
493+
* // Perform some mutations.
502494
*
503-
* <p>Sample code:
495+
* ConsistencyToken token = client.generateConsistencyToken("table-id");
496+
* while(!client.isConsistent(token)) {
497+
* Thread.sleep(100);
498+
* }
504499
*
505-
* <pre>{@code
506-
* try(BigtableTableAdminClient client = BigtableTableAdminClient.create(InstanceName.of("[PROJECT]", "[INSTANCE]"))) {
507-
* boolean consistent = client.isConsistentAsync("tableId", token);
500+
* // Now all clusters are consistent
508501
* }
509502
* }</pre>
510503
*/
511-
public ApiFuture<Boolean> isConsistentAsync(String tableId, ConsistencyToken token) {
512-
ApiFuture<CheckConsistencyResponse> checkConsResp =
513-
stub.checkConsistencyCallable().futureCall(token.toProto(getTableName(tableId)));
504+
public boolean isConsistent(ConsistencyToken token) {
505+
return awaitFuture(isConsistentAsync(token));
506+
}
507+
508+
@VisibleForTesting
509+
ApiFuture<Boolean> isConsistentAsync(ConsistencyToken token) {
510+
ApiFuture<CheckConsistencyResponse> checkConsResp = stub.checkConsistencyCallable()
511+
.futureCall(token.toProto(instanceName));
514512

515513
return ApiFutures.transform(
516514
checkConsResp,
@@ -523,6 +521,8 @@ public Boolean apply(CheckConsistencyResponse input) {
523521
MoreExecutors.directExecutor());
524522
}
525523

524+
// TODO(igorbernstein2): add awaitConsist() & awaitConsistAsync() that generate & poll a token
525+
526526
/**
527527
* Helper method to construct the table name in format:
528528
* projects/{project}/instances/{instance}/tables/{tableId}

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

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,63 +16,39 @@
1616
package com.google.cloud.bigtable.admin.v2.models;
1717

1818
import com.google.api.core.InternalApi;
19+
import com.google.api.core.InternalExtensionOnly;
20+
import com.google.auto.value.AutoValue;
1921
import com.google.bigtable.admin.v2.CheckConsistencyRequest;
2022
import com.google.bigtable.admin.v2.GenerateConsistencyTokenResponse;
21-
import com.google.common.annotations.VisibleForTesting;
22-
import com.google.common.base.MoreObjects;
23-
import com.google.common.base.Objects;
23+
import com.google.bigtable.admin.v2.InstanceName;
24+
import com.google.bigtable.admin.v2.TableName;
25+
import com.google.common.base.Preconditions;
2426

2527
/**
2628
* Wrapper for {@link GenerateConsistencyTokenResponse#getConsistencyToken()}
2729
*
2830
* <p>Cannot be created. They are obtained by invoking {@link
2931
* com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient#generateConsistencyToken(String)}
3032
*/
31-
public final class ConsistencyToken {
32-
private final String token;
33-
34-
@InternalApi
35-
public static ConsistencyToken fromProto(GenerateConsistencyTokenResponse proto) {
36-
return new ConsistencyToken(proto.getConsistencyToken());
33+
@InternalExtensionOnly
34+
@AutoValue
35+
public abstract class ConsistencyToken {
36+
public static ConsistencyToken of(TableName tableName, String token) {
37+
return new AutoValue_ConsistencyToken(tableName, token);
3738
}
3839

39-
private ConsistencyToken(String token) {
40-
this.token = token;
41-
}
40+
abstract TableName getTableName();
41+
abstract String getToken();
4242

43-
// TODO(igorbernstein): tableName should be part of the token and be parameterized
4443
@InternalApi
45-
public CheckConsistencyRequest toProto(String tableName) {
44+
public CheckConsistencyRequest toProto(InstanceName instanceName) {
45+
Preconditions.checkArgument(
46+
instanceName.equals(InstanceName.of(getTableName().getProject(), getTableName().getInstance())),
47+
"Consistency tokens are only valid within a single instance.");
48+
4649
return CheckConsistencyRequest.newBuilder()
47-
.setName(tableName)
48-
.setConsistencyToken(token)
50+
.setName(getTableName().toString())
51+
.setConsistencyToken(getToken())
4952
.build();
5053
}
51-
52-
@VisibleForTesting
53-
String getToken() {
54-
return token;
55-
}
56-
57-
@Override
58-
public boolean equals(Object o) {
59-
if (this == o) {
60-
return true;
61-
}
62-
if (o == null || getClass() != o.getClass()) {
63-
return false;
64-
}
65-
ConsistencyToken that = (ConsistencyToken) o;
66-
return Objects.equal(token, that.token);
67-
}
68-
69-
@Override
70-
public int hashCode() {
71-
return Objects.hashCode(token);
72-
}
73-
74-
@Override
75-
public String toString() {
76-
return MoreObjects.toStringHelper(this).add("token", token).toString();
77-
}
7854
}

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ public void testGenerateConsistencyToken() {
496496
ConsistencyToken actualResult = adminClient.generateConsistencyToken(TABLE_NAME.getTable());
497497

498498
// Verify
499-
assertThat(actualResult).isEqualTo(ConsistencyToken.fromProto(expectedResponse));
499+
assertThat(actualResult).isEqualTo(ConsistencyToken.of(TABLE_NAME, "fakeToken"));
500500
}
501501

502502
@Test
@@ -519,7 +519,7 @@ public void testGenerateConsistencyTokenAsync() throws Exception {
519519
.generateConsistencyTokenAsync(TABLE_NAME.getTable());
520520

521521
// Verify
522-
assertThat(actualResult.get()).isEqualTo(ConsistencyToken.fromProto(expectedResponse));
522+
assertThat(actualResult.get()).isEqualTo(ConsistencyToken.of(TABLE_NAME, "fakeToken"));
523523
}
524524

525525
@Test
@@ -538,13 +538,9 @@ public void testCheckConsistencyToken() {
538538
.thenReturn(ApiFutures.immediateFuture(expectedResponse));
539539

540540
// Execute
541-
ConsistencyToken actualToken = ConsistencyToken.fromProto(
542-
GenerateConsistencyTokenResponse.newBuilder()
543-
.setConsistencyToken("fakeToken")
544-
.build()
545-
);
541+
ConsistencyToken actualToken = ConsistencyToken.of(TABLE_NAME, "fakeToken");
546542

547-
boolean actualResult = adminClient.isConsistent(TABLE_NAME.getTable(), actualToken);
543+
boolean actualResult = adminClient.isConsistent(actualToken);
548544

549545
// Verify
550546
assertThat(actualResult).isTrue();

google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableTableAdminClientIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ public void checkConsistency() {
235235
tableAdmin.createTable(CreateTableRequest.of(tableId));
236236
ConsistencyToken consistencyToken = tableAdmin.generateConsistencyToken(tableId);
237237
assertNotNull(consistencyToken);
238-
boolean consistent = tableAdmin.isConsistent(tableId, consistencyToken);
238+
boolean consistent = tableAdmin.isConsistent(consistencyToken);
239239
assertTrue(consistent);
240240
} finally {
241241
tableAdmin.deleteTable(tableId);

google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/ConsistencyTokenTest.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,47 @@
1515
*/
1616
package com.google.cloud.bigtable.admin.v2.models;
1717

18-
import static org.junit.Assert.assertEquals;
18+
import static com.google.common.truth.Truth.assertThat;
1919

20-
import com.google.bigtable.admin.v2.GenerateConsistencyTokenResponse;
20+
import com.google.bigtable.admin.v2.CheckConsistencyRequest;
21+
import com.google.bigtable.admin.v2.InstanceName;
22+
import com.google.bigtable.admin.v2.TableName;
2123
import org.junit.Test;
2224
import org.junit.runner.RunWith;
2325
import org.junit.runners.JUnit4;
2426

2527
@RunWith(JUnit4.class)
2628
public class ConsistencyTokenTest {
29+
private static final InstanceName INSTANCE_NAME = InstanceName.of("my-project", "my-instance");
30+
private static final TableName TABLE_NAME = TableName.of(INSTANCE_NAME.getProject(), INSTANCE_NAME.getInstance(), "my-table");
31+
private static final String TOKEN_VALUE = "87282hgwd8yg";
32+
33+
@Test
34+
public void testToProto() {
35+
ConsistencyToken token = ConsistencyToken.of(TABLE_NAME, TOKEN_VALUE);
36+
37+
assertThat(token.toProto(INSTANCE_NAME)).isEqualTo(
38+
CheckConsistencyRequest.newBuilder()
39+
.setName(TABLE_NAME.toString())
40+
.setConsistencyToken(TOKEN_VALUE)
41+
.build()
42+
);
43+
}
44+
2745
@Test
28-
public void fromJsonTest() {
29-
ConsistencyToken tokenResponse =
30-
ConsistencyToken.fromProto(
31-
GenerateConsistencyTokenResponse.newBuilder()
32-
.setConsistencyToken("87282hgwd8yg")
33-
.build());
34-
35-
assertEquals("87282hgwd8yg", tokenResponse.getToken());
46+
public void testInstanceMismatch() {
47+
ConsistencyToken token = ConsistencyToken.of(TABLE_NAME, TOKEN_VALUE);
48+
49+
InstanceName otherInstanceName = InstanceName.of("my-project", "other-instance");
50+
51+
Exception actualError = null;
52+
53+
try {
54+
token.toProto(otherInstanceName);
55+
} catch (Exception e) {
56+
actualError = e;
57+
}
58+
59+
assertThat(actualError).isInstanceOf(IllegalArgumentException.class);
3660
}
3761
}

0 commit comments

Comments
 (0)