@@ -603,10 +603,17 @@ public void runInReadTx(Runnable runnable) {
603
603
}
604
604
}
605
605
606
+ /**
607
+ * Calls {@link #callInReadTx(Callable)} and retries in case a DbException is thrown.
608
+ * If the given amount of attempts is reached, the last DbException will be thrown.
609
+ * Experimental: API might change.
610
+ */
606
611
@ Experimental
607
612
public <T > T callInReadTxWithRetry (Callable <T > callable , int attempts , int initialBackOffInMs , boolean logAndHeal ) {
608
613
if (attempts == 1 ) {
609
614
return callInReadTx (callable );
615
+ } else if (attempts < 1 ) {
616
+ throw new IllegalArgumentException ("Illegal value of attempts: " + attempts );
610
617
}
611
618
long backoffInMs = initialBackOffInMs ;
612
619
DbException lastException = null ;
@@ -648,9 +655,9 @@ public <T> T callInReadTxWithRetry(Callable<T> callable, int attempts, int initi
648
655
* This allows multiple read operations (gets) using a single consistent state of data.
649
656
* Also, for a high number of read operations (thousands, e.g. in loops),
650
657
* it is advised to run them in a single read transaction for efficiency reasons.
651
- * Note that any exception thrown by the given Callable will be wrapped in a RuntimeException.
658
+ * Note that an exception thrown by the given Callable will be wrapped in a RuntimeException, if the exception is
659
+ * not a RuntimeException itself.
652
660
*/
653
-
654
661
public <T > T callInReadTx (Callable <T > callable ) {
655
662
Transaction tx = this .activeTx .get ();
656
663
// Only if not already set, allowing to call it recursively with first (outer) TX
@@ -659,7 +666,7 @@ public <T> T callInReadTx(Callable<T> callable) {
659
666
activeTx .set (tx );
660
667
try {
661
668
return callable .call ();
662
- } catch (DbException e ) {
669
+ } catch (RuntimeException e ) {
663
670
throw e ;
664
671
} catch (Exception e ) {
665
672
throw new RuntimeException ("Callable threw exception" , e );
0 commit comments