use of com.google.cloud.spanner.Struct in project google-cloud-java by GoogleCloudPlatform.
the class ITTransactionTest method userExceptionPreventsCommit.
@Test
public void userExceptionPreventsCommit() {
class UserException extends Exception {
UserException(String message) {
super(message);
}
}
final String key = uniqueKey();
TransactionCallable<Void> callable = new TransactionCallable<Void>() {
@Override
public Void run(TransactionContext transaction) throws UserException {
transaction.buffer(Mutation.newInsertOrUpdateBuilder("T").set("K").to(key).build());
throw new UserException("User failure");
}
};
try {
client.readWriteTransaction().run(callable);
fail("Expected user exception");
} catch (SpannerException e) {
assertThat(e.getErrorCode()).isEqualTo(ErrorCode.UNKNOWN);
assertThat(e.getMessage()).contains("User failure");
assertThat(e.getCause()).isInstanceOf(UserException.class);
}
Struct row = client.singleUse(TimestampBound.strong()).readRow("T", Key.of(key), Arrays.asList("K"));
assertThat(row).isNull();
}
use of com.google.cloud.spanner.Struct in project google-cloud-java by GoogleCloudPlatform.
the class ITTransactionTest method readAbort.
@Test
public void readAbort() throws InterruptedException {
final String key1 = uniqueKey();
final String key2 = uniqueKey();
client.write(Arrays.asList(Mutation.newInsertBuilder("T").set("K").to(key1).set("V").to(0).build(), Mutation.newInsertBuilder("T").set("K").to(key2).set("V").to(1).build()));
final CountDownLatch t1Started = new CountDownLatch(1);
final CountDownLatch t1Done = new CountDownLatch(1);
final CountDownLatch t2Running = new CountDownLatch(1);
final CountDownLatch t2Done = new CountDownLatch(1);
// Thread 1 performs a read before notifying that it has started and allowing
// thread 2 to start. This ensures that it establishes a senior lock priority relative to
// thread 2. It then waits for thread 2 to read, so that both threads have shared locks on
// key1, before continuing to commit; the act of committing means that thread 1's lock is
// upgraded and thread 2's transaction is aborted. When thread 1 is done, thread 2 tries a
// second read, which will abort. Both threads will mask SpannerExceptions to ensure that
// the implementation does not require TransactionCallable to propagate them.
Thread t1 = new Thread() {
@Override
public void run() {
client.readWriteTransaction().run(new TransactionCallable<Void>() {
@Override
public Void run(TransactionContext transaction) throws SpannerException {
try {
Struct row = transaction.readRow("T", Key.of(key1), Arrays.asList("V"));
t1Started.countDown();
Uninterruptibles.awaitUninterruptibly(t2Running);
transaction.buffer(Mutation.newUpdateBuilder("T").set("K").to(key1).set("V").to(row.getLong(0) + 1).build());
return null;
} catch (SpannerException e) {
if (e.getErrorCode() == ErrorCode.ABORTED) {
assertThat(e).isInstanceOf(AbortedException.class);
assertThat(((AbortedException) e).getRetryDelayInMillis()).isNotEqualTo(-1L);
}
throw new RuntimeException("Swallowed exception: " + e.getMessage());
}
}
});
t1Done.countDown();
}
};
Thread t2 = new Thread() {
@Override
public void run() {
client.readWriteTransaction().run(new TransactionCallable<Void>() {
@Override
public Void run(TransactionContext transaction) throws SpannerException {
try {
Struct r1 = transaction.readRow("T", Key.of(key1), Arrays.asList("V"));
t2Running.countDown();
Uninterruptibles.awaitUninterruptibly(t1Done);
Struct r2 = transaction.readRow("T", Key.of(key2), Arrays.asList("V"));
transaction.buffer(Mutation.newUpdateBuilder("T").set("K").to(key2).set("V").to(r1.getLong(0) + r2.getLong(0)).build());
return null;
} catch (SpannerException e) {
if (e.getErrorCode() == ErrorCode.ABORTED) {
assertThat(e).isInstanceOf(AbortedException.class);
assertThat(((AbortedException) e).getRetryDelayInMillis()).isNotEqualTo(-1L);
}
throw new RuntimeException("Swallowed exception: " + e.getMessage());
}
}
});
t2Done.countDown();
}
};
t1.start();
Uninterruptibles.awaitUninterruptibly(t1Started);
// Thread 2 will abort on the first attempt and should retry; wait for completion to confirm.
t2.start();
assertThat(t2Done.await(1, TimeUnit.MINUTES)).isTrue();
// Check that both transactions effects are visible.
assertThat(client.singleUse(TimestampBound.strong()).readRow("T", Key.of(key1), Arrays.asList("V")).getLong(0)).isEqualTo(1);
assertThat(client.singleUse(TimestampBound.strong()).readRow("T", Key.of(key2), Arrays.asList("V")).getLong(0)).isEqualTo(2);
}
use of com.google.cloud.spanner.Struct in project google-cloud-java by GoogleCloudPlatform.
the class ITWriteTest method writeString.
@Test
public void writeString() {
write(baseInsert().set("StringValue").to("V1").build());
Struct row = readLastRow("StringValue");
assertThat(row.isNull(0)).isFalse();
assertThat(row.getString(0)).isEqualTo("V1");
}
use of com.google.cloud.spanner.Struct in project google-cloud-java by GoogleCloudPlatform.
the class ITWriteTest method writeTimestamp.
@Test
public void writeTimestamp() {
Timestamp timestamp = Timestamp.parseTimestamp("2016-09-15T00:00:00.111111Z");
write(baseInsert().set("TimestampValue").to(timestamp).build());
Struct row = readLastRow("TimestampValue");
assertThat(row.isNull(0)).isFalse();
assertThat(row.getTimestamp(0)).isEqualTo(timestamp);
}
use of com.google.cloud.spanner.Struct in project google-cloud-java by GoogleCloudPlatform.
the class ITWriteTest method writeBytesArrayNull.
@Test
public void writeBytesArrayNull() {
write(baseInsert().set("BytesArrayValue").toBytesArray(null).build());
Struct row = readLastRow("BytesArrayValue");
assertThat(row.isNull(0)).isTrue();
}
Aggregations