@@ -306,12 +306,23 @@ private void createTxnAsync(final SettableApiFuture<Void> res) {
306
306
307
307
void commit () {
308
308
try {
309
- commitResponse = commitAsync ().get ();
310
- } catch (InterruptedException e ) {
309
+ // Normally, Gax will take care of any timeouts, but we add a timeout for getting the value
310
+ // from the future here as well to make sure the call always finishes, even if the future
311
+ // never resolves.
312
+ commitResponse =
313
+ commitAsync ()
314
+ .get (
315
+ rpc .getCommitRetrySettings ().getTotalTimeout ().getSeconds () + 5 ,
316
+ TimeUnit .SECONDS );
317
+ } catch (InterruptedException | TimeoutException e ) {
311
318
if (commitFuture != null ) {
312
319
commitFuture .cancel (true );
313
320
}
314
- throw SpannerExceptionFactory .propagateInterrupt (e );
321
+ if (e instanceof InterruptedException ) {
322
+ throw SpannerExceptionFactory .propagateInterrupt ((InterruptedException ) e );
323
+ } else {
324
+ throw SpannerExceptionFactory .propagateTimeout ((TimeoutException ) e );
325
+ }
315
326
} catch (ExecutionException e ) {
316
327
throw SpannerExceptionFactory .newSpannerException (e .getCause () == null ? e : e .getCause ());
317
328
}
@@ -422,6 +433,14 @@ public void run() {
422
433
commitFuture .addListener (
423
434
() -> {
424
435
try (IScope ignore = tracer .withSpan (opSpan )) {
436
+ if (!commitFuture .isDone ()) {
437
+ // This should not be possible, considering that we are in a listener for the
438
+ // future, but we add a result here as well as a safety precaution.
439
+ res .setException (
440
+ SpannerExceptionFactory .newSpannerException (
441
+ ErrorCode .INTERNAL , "commitFuture is not done" ));
442
+ return ;
443
+ }
425
444
com .google .spanner .v1 .CommitResponse proto = commitFuture .get ();
426
445
if (!proto .hasCommitTimestamp ()) {
427
446
throw newSpannerException (
@@ -430,30 +449,35 @@ public void run() {
430
449
span .addAnnotation ("Commit Done" );
431
450
opSpan .end ();
432
451
res .set (new CommitResponse (proto ));
433
- } catch (Throwable e ) {
434
- if (e instanceof ExecutionException ) {
435
- e =
436
- SpannerExceptionFactory .newSpannerException (
437
- e .getCause () == null ? e : e .getCause ());
438
- } else if (e instanceof InterruptedException ) {
439
- e = SpannerExceptionFactory .propagateInterrupt ((InterruptedException ) e );
440
- } else {
441
- e = SpannerExceptionFactory .newSpannerException (e );
452
+ } catch (Throwable throwable ) {
453
+ SpannerException resultException ;
454
+ try {
455
+ if (throwable instanceof ExecutionException ) {
456
+ resultException =
457
+ SpannerExceptionFactory .asSpannerException (
458
+ throwable .getCause () == null ? throwable : throwable .getCause ());
459
+ } else if (throwable instanceof InterruptedException ) {
460
+ resultException =
461
+ SpannerExceptionFactory .propagateInterrupt (
462
+ (InterruptedException ) throwable );
463
+ } else {
464
+ resultException = SpannerExceptionFactory .asSpannerException (throwable );
465
+ }
466
+ span .addAnnotation ("Commit Failed" , resultException );
467
+ opSpan .setStatus (resultException );
468
+ opSpan .end ();
469
+ res .setException (onError (resultException , false ));
470
+ } catch (Throwable unexpectedError ) {
471
+ // This is a safety precaution to make sure that a result is always returned.
472
+ res .setException (unexpectedError );
442
473
}
443
- span .addAnnotation ("Commit Failed" , e );
444
- opSpan .setStatus (e );
445
- opSpan .end ();
446
- res .setException (onError ((SpannerException ) e , false ));
447
474
}
448
475
},
449
476
MoreExecutors .directExecutor ());
450
477
} catch (InterruptedException e ) {
451
478
res .setException (SpannerExceptionFactory .propagateInterrupt (e ));
452
479
} catch (TimeoutException e ) {
453
480
res .setException (SpannerExceptionFactory .propagateTimeout (e ));
454
- } catch (ExecutionException e ) {
455
- res .setException (
456
- SpannerExceptionFactory .newSpannerException (e .getCause () == null ? e : e .getCause ()));
457
481
} catch (Throwable e ) {
458
482
res .setException (
459
483
SpannerExceptionFactory .newSpannerException (e .getCause () == null ? e : e .getCause ()));
0 commit comments