Skip to content

Commit

Permalink
fix: AsyncTransactionManager did not propagate statement errors (#516)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
olavloite committed Oct 16, 2020
1 parent 273f40c commit 4b8b845
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
Expand Up @@ -121,6 +121,7 @@ public void onSuccess(I result) {
@Override
public void onFailure(Throwable t) {
mgr.onError(t);
statementResult.setException(t);
txnResult.setException(t);
}

Expand All @@ -132,6 +133,7 @@ public void onSuccess(O result) {
MoreExecutors.directExecutor());
} catch (Throwable t) {
mgr.onError(t);
statementResult.setException(t);
txnResult.setException(t);
}
}
Expand Down
Expand Up @@ -60,6 +60,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -1112,4 +1113,48 @@ public ApiFuture<Void> apply(TransactionContext txn, Struct input)
}
}
}

@Test
public void asyncTransactionManager_shouldPropagateStatementFailure()
throws ExecutionException, InterruptedException, TimeoutException {
DatabaseClient dbClient = client();
try (AsyncTransactionManager transactionManager = dbClient.transactionManagerAsync()) {
TransactionContextFuture txnContextFuture = transactionManager.beginAsync();
AsyncTransactionStep<Void, Long> updateFuture =
txnContextFuture.then(
new AsyncTransactionFunction<Void, Long>() {
@Override
public ApiFuture<Long> apply(TransactionContext txn, Void input) throws Exception {
return txn.executeUpdateAsync(INVALID_UPDATE_STATEMENT);
}
},
executor);
final SettableApiFuture<Void> res = SettableApiFuture.create();
ApiFutures.addCallback(
updateFuture,
new ApiFutureCallback<Long>() {
@Override
public void onFailure(Throwable throwable) {
// Check that we got the expected failure.
try {
assertThat(throwable).isInstanceOf(SpannerException.class);
SpannerException e = (SpannerException) throwable;
assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT);
assertThat(e.getMessage()).contains("invalid statement");
res.set(null);
} catch (Throwable t) {
res.setException(t);
}
}

@Override
public void onSuccess(Long aLong) {
res.setException(new AssertionError("Statement should not succeed."));
}
},
executor);

assertThat(res.get(10L, TimeUnit.SECONDS)).isNull();
}
}
}

0 comments on commit 4b8b845

Please sign in to comment.