Skip to content

Commit 4b8b845

Browse files
authored
fix: AsyncTransactionManager did not propagate statement errors (#516)
* fix: AsyncTransactionManager did not propagate statement errors Invalid statements or other statements that would cause an error would not cause the returned ApiFuture to fail. Fixes #514 * test: use existing invalid statement in test
1 parent 273f40c commit 4b8b845

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionContextFutureImpl.java

+2
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public void onSuccess(I result) {
121121
@Override
122122
public void onFailure(Throwable t) {
123123
mgr.onError(t);
124+
statementResult.setException(t);
124125
txnResult.setException(t);
125126
}
126127

@@ -132,6 +133,7 @@ public void onSuccess(O result) {
132133
MoreExecutors.directExecutor());
133134
} catch (Throwable t) {
134135
mgr.onError(t);
136+
statementResult.setException(t);
135137
txnResult.setException(t);
136138
}
137139
}

google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerTest.java

+45
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import java.util.concurrent.Executor;
6161
import java.util.concurrent.Executors;
6262
import java.util.concurrent.TimeUnit;
63+
import java.util.concurrent.TimeoutException;
6364
import java.util.concurrent.atomic.AtomicInteger;
6465
import org.junit.Test;
6566
import org.junit.runner.RunWith;
@@ -1112,4 +1113,48 @@ public ApiFuture<Void> apply(TransactionContext txn, Struct input)
11121113
}
11131114
}
11141115
}
1116+
1117+
@Test
1118+
public void asyncTransactionManager_shouldPropagateStatementFailure()
1119+
throws ExecutionException, InterruptedException, TimeoutException {
1120+
DatabaseClient dbClient = client();
1121+
try (AsyncTransactionManager transactionManager = dbClient.transactionManagerAsync()) {
1122+
TransactionContextFuture txnContextFuture = transactionManager.beginAsync();
1123+
AsyncTransactionStep<Void, Long> updateFuture =
1124+
txnContextFuture.then(
1125+
new AsyncTransactionFunction<Void, Long>() {
1126+
@Override
1127+
public ApiFuture<Long> apply(TransactionContext txn, Void input) throws Exception {
1128+
return txn.executeUpdateAsync(INVALID_UPDATE_STATEMENT);
1129+
}
1130+
},
1131+
executor);
1132+
final SettableApiFuture<Void> res = SettableApiFuture.create();
1133+
ApiFutures.addCallback(
1134+
updateFuture,
1135+
new ApiFutureCallback<Long>() {
1136+
@Override
1137+
public void onFailure(Throwable throwable) {
1138+
// Check that we got the expected failure.
1139+
try {
1140+
assertThat(throwable).isInstanceOf(SpannerException.class);
1141+
SpannerException e = (SpannerException) throwable;
1142+
assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT);
1143+
assertThat(e.getMessage()).contains("invalid statement");
1144+
res.set(null);
1145+
} catch (Throwable t) {
1146+
res.setException(t);
1147+
}
1148+
}
1149+
1150+
@Override
1151+
public void onSuccess(Long aLong) {
1152+
res.setException(new AssertionError("Statement should not succeed."));
1153+
}
1154+
},
1155+
executor);
1156+
1157+
assertThat(res.get(10L, TimeUnit.SECONDS)).isNull();
1158+
}
1159+
}
11151160
}

0 commit comments

Comments
 (0)