/blueprints-core/src/main/java/com/tinkerpop/blueprints/util/TransactionRetryStrategy.java
https://github.com/pangloss/blueprints · Java · 179 lines · 112 code · 33 blank · 34 comment · 8 complexity · b527b721df374114d4f80d650798e8ab MD5 · raw file
- package com.tinkerpop.blueprints.util;
- import com.tinkerpop.blueprints.TransactionalGraph;
- import java.util.HashSet;
- import java.util.Set;
- /**
- * The strategy for executing a transaction.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
- public interface TransactionRetryStrategy<T> {
- /**
- * Executes the TransactionWork with a give strategy.
- *
- * @param graph The TransactionalGraph to mutate.
- * @param work The work to do on the Graph.
- * @return The return value from TransactionWork.
- */
- public T execute(TransactionalGraph graph, TransactionWork<T> work);
- /**
- * Executes the work committing if possible and rolling back on failure. On failure, an exception is reported.
- */
- public static class OneAndDone<T> implements TransactionRetryStrategy<T> {
- public T execute(final TransactionalGraph graph, final TransactionWork<T> work) {
- T returnValue;
- try {
- returnValue = work.execute(graph);
- graph.commit();
- } catch (Exception e) {
- graph.rollback();
- throw new RuntimeException(e);
- }
- return returnValue;
- }
- }
- /**
- * Executes the work committing if possible and rolling back on failure. On failure no exception is reported.
- */
- public static class FireAndForget<T> implements TransactionRetryStrategy<T> {
- public T execute(final TransactionalGraph graph, final TransactionWork<T> work) {
- T returnValue = null;
- try {
- returnValue = work.execute(graph);
- graph.commit();
- } catch (Exception e) {
- graph.rollback();
- }
- return returnValue;
- }
- }
- /**
- * Executes the work with a number of retries and with a number of milliseconds delay between each try.
- */
- public static class DelayedRetry<T> extends AbstractRetryStrategy<T> {
- public static final long DEFAULT_DELAY_MS = 20;
- private final long delayBetweenRetry;
- public DelayedRetry() {
- this(DEFAULT_TRIES, DEFAULT_DELAY_MS);
- }
- public DelayedRetry(final int tries, final long delayBetweenRetry) {
- this(tries, delayBetweenRetry, new HashSet<Class>());
- }
- public DelayedRetry(final int tries, final long delayBetweenRetry, final Set<Class> exceptionsToRetryOn) {
- super(tries, exceptionsToRetryOn);
- this.delayBetweenRetry = delayBetweenRetry;
- }
- @Override
- long getDelay(final int retryCount) {
- return this.delayBetweenRetry;
- }
- }
- /**
- * Executes the work with a number of retries and with a exponentially increasing number of milliseconds
- * between each retry.
- */
- public static class ExponentialBackoff<T> extends AbstractRetryStrategy<T> {
- public static final long DEFAULT_DELAY_MS = 20;
- private final long initialDelay;
- public ExponentialBackoff() {
- this(DEFAULT_TRIES, DEFAULT_DELAY_MS);
- }
- public ExponentialBackoff(final int tries, final long initialDelay) {
- this(tries, initialDelay, new HashSet<Class>());
- }
- public ExponentialBackoff(final int tries, final long initialDelay, final Set<Class> exceptionsToRetryOn) {
- super(tries, exceptionsToRetryOn);
- this.initialDelay = initialDelay;
- }
- @Override
- long getDelay(final int retryCount) {
- return (long) (initialDelay * Math.pow(2, retryCount));
- }
- }
- /**
- * Base class for strategy that require a retry.
- */
- public static abstract class AbstractRetryStrategy<T> implements TransactionRetryStrategy<T> {
- public static final int DEFAULT_TRIES = 8;
- protected final int tries;
- protected final Set<Class> exceptionsToRetryOn;
- public AbstractRetryStrategy() {
- this(DEFAULT_TRIES, new HashSet<Class>());
- }
- public AbstractRetryStrategy(final int tries, final Set<Class> exceptionsToRetryOn) {
- this.tries = tries;
- this.exceptionsToRetryOn = exceptionsToRetryOn;
- }
- abstract long getDelay(int retryCount);
- public T execute(final TransactionalGraph graph, final TransactionWork<T> work) {
- T 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(getDelay(ix)); } catch (InterruptedException ie) { }
- try {
- returnValue = work.execute(graph);
- graph.commit();
- // need to exit the function here so that retries don't happen
- return returnValue;
- } catch (Exception ex) {
- graph.rollback();
- // retry if this is an allowed exception otherwise, just throw and go
- boolean retry = false;
- if (this.exceptionsToRetryOn.size() == 0)
- retry = true;
- else {
- for (Class exceptionToRetryOn : this.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);
- }
- }
- }