/** * Creates a generic retry function to be passed to the {@link * Workload#attempt(java.util.function.BiFunction)} method. */ private static <R> BiFunction<Graph, Function<Graph, R>, R> retry( final int tries, final Set<Class> exceptionsToRetryOn, final Function<Integer, Long> delay) { return (g, w) -> { R returnValue; // this is the default exception...it may get reassgined during retries Exception previousException = new RuntimeException("Exception initialized when trying commit"); // try to commit a few times for (int ix = 0; ix < tries; ix++) { // increase time after each failed attempt though there is no delay on the first try if (ix > 0) try { Thread.sleep(delay.apply(ix)); } catch (InterruptedException ignored) { } try { returnValue = w.apply(g); g.tx().commit(); // need to exit the function here so that retries don't happen return returnValue; } catch (Exception ex) { g.tx().rollback(); // retry if this is an allowed exception otherwise, just throw and go boolean retry = false; if (exceptionsToRetryOn.size() == 0) retry = true; else { for (Class exceptionToRetryOn : exceptionsToRetryOn) { if (ex.getClass().equals(exceptionToRetryOn)) { retry = true; break; } } } if (!retry) { throw new RuntimeException(ex); } previousException = ex; } } // the exception just won't go away after all the retries throw new RuntimeException(previousException); }; }
/** * Executes the {@link Workload} committing if possible and rolling back on failure. On failure * no exception is reported. */ public R fireAndForget() { return attempt( (g, w) -> { R result = null; try { result = w.apply(g); g.tx().commit(); } catch (Throwable t) { g.tx().rollback(); } return result; }); }
/** * Executes the {@link Workload} committing if possible and rolling back on failure. On failure, * an exception is reported. */ public R oneAndDone() { return attempt( (g, w) -> { try { R result = w.apply(g); g.tx().commit(); return result; } catch (Throwable t) { g.tx().rollback(); throw new RuntimeException(t); } }); }