Skip to content

Commit 969f7fd

Browse files
author
Brian Chen
authored
fix: handle thrown exceptions in runAsyncTransaction callback (#671)
1 parent 7f1fee6 commit 969f7fd

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

google-cloud-firestore/src/main/java/com/google/cloud/firestore/TransactionRunner.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,28 +145,35 @@ public void run() {
145145
* Invokes the user callback on the user callback executor and returns the user-provided result.
146146
*/
147147
private SettableApiFuture<T> invokeUserCallback() {
148-
final SettableApiFuture<T> callbackResult = SettableApiFuture.create();
148+
final SettableApiFuture<T> returnedResult = SettableApiFuture.create();
149+
149150
userCallbackExecutor.execute(
150151
new Runnable() {
151152
@Override
152153
public void run() {
154+
ApiFuture<T> userCallbackResult;
155+
try {
156+
userCallbackResult = userCallback.updateCallback(transaction);
157+
} catch (Exception e) {
158+
userCallbackResult = ApiFutures.immediateFailedFuture(e);
159+
}
153160
ApiFutures.addCallback(
154-
userCallback.updateCallback(transaction),
161+
userCallbackResult,
155162
new ApiFutureCallback<T>() {
156163
@Override
157164
public void onFailure(Throwable t) {
158-
callbackResult.setException(t);
165+
returnedResult.setException(t);
159166
}
160167

161168
@Override
162169
public void onSuccess(T result) {
163-
callbackResult.set(result);
170+
returnedResult.set(result);
164171
}
165172
},
166-
MoreExecutors.directExecutor());
173+
firestoreExecutor);
167174
}
168175
});
169-
return callbackResult;
176+
return returnedResult;
170177
}
171178

172179
/** A callback that invokes the BeginTransaction callback. */

google-cloud-firestore/src/test/java/com/google/cloud/firestore/TransactionTest.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ public String updateCallback(Transaction transaction) throws Exception {
253253
}
254254

255255
@Test
256-
public void rollbackOnCallbackErrorAsync() {
256+
public void rollbackOnCallbackApiFutureErrorAsync() {
257257
doReturn(beginResponse())
258258
.doReturn(rollbackResponse())
259259
.when(firestoreMock)
@@ -339,6 +339,31 @@ public ApiFuture<String> updateCallback(Transaction transaction) {
339339
assertEquals(1, requests.size());
340340
}
341341

342+
@Test
343+
public void noRollbackOnThrownExceptionAsync() {
344+
doReturn(beginResponse())
345+
.doReturn(rollbackResponse())
346+
.when(firestoreMock)
347+
.sendRequest(requestCapture.capture(), Matchers.<UnaryCallable<Message, Message>>any());
348+
349+
ApiFuture<String> transaction =
350+
firestoreMock.runAsyncTransaction(
351+
new Transaction.AsyncFunction<String>() {
352+
@Override
353+
public ApiFuture<String> updateCallback(Transaction transaction) {
354+
throw new RuntimeException("User exception");
355+
}
356+
},
357+
options);
358+
359+
try {
360+
transaction.get();
361+
fail();
362+
} catch (Exception e) {
363+
assertTrue(e.getMessage().endsWith("User exception"));
364+
}
365+
}
366+
342367
@Test
343368
public void limitsRetriesWithFailure() {
344369
ResponseStubber responseStubber =

google-cloud-firestore/src/test/java/com/google/cloud/firestore/it/ITSystemTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,24 @@ public String updateCallback(Transaction transaction) {
688688
}
689689
}
690690

691+
@Test
692+
public void asyncTxFailsWithUserError() throws Exception {
693+
try {
694+
firestore
695+
.runAsyncTransaction(
696+
new Transaction.AsyncFunction<String>() {
697+
@Override
698+
public ApiFuture<String> updateCallback(Transaction transaction) {
699+
throw new RuntimeException("User exception");
700+
}
701+
})
702+
.get();
703+
fail();
704+
} catch (Exception e) {
705+
assertTrue(e.getMessage().endsWith("User exception"));
706+
}
707+
}
708+
691709
@Test
692710
public void doesNotRetryTransactionsWithFailedPreconditions() {
693711
final DocumentReference documentReference = randomColl.document();

0 commit comments

Comments
 (0)