package me.prettyprint.cassandra.service; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import java.util.Set; /** * What should the client do if a call to cassandra node fails and we suspect that the node is * down. (e.g. it's a communication error, not an application error). * * {@value #FAIL_FAST} will return the error as is to the user and not try anything smart * * {@value #ON_FAIL_TRY_ONE_NEXT_AVAILABLE} will try one more random server before returning to the * user with an error * * {@value #ON_FAIL_TRY_ALL_AVAILABLE} will try all available servers in the cluster before giving * up and returning the communication error to the user. * */ public class FailoverPolicy<E extends Throwable> { /** On communication failure, just return the error to the client and don't retry */ public static FailoverPolicy FAIL_FAST = new FailoverPolicy(0, 0); /** On communication error try one more server before giving up */ public static FailoverPolicy ON_FAIL_TRY_ONE_NEXT_AVAILABLE = new FailoverPolicy(1, 0); /** On communication error try all known servers before giving up */ public static FailoverPolicy ON_FAIL_TRY_ALL_AVAILABLE = new FailoverPolicy(Integer.MAX_VALUE - 1, 0); public final int numRetries; public final int sleepBetweenHostsMilli; /** Optional set of classes representing Exceptions/Errors for which retry should not happen. */ public final Set<Class<E>> dontRetry; public FailoverPolicy(int numRetries, int sleepBwHostsMilli) { this.numRetries = numRetries; sleepBetweenHostsMilli = sleepBwHostsMilli; dontRetry = ImmutableSet.of(); } public FailoverPolicy(int numRetries, int sleepBwHostsMilli, Class<E> dontRetryForType) { this.numRetries = numRetries; sleepBetweenHostsMilli = sleepBwHostsMilli; dontRetry = ImmutableSet.of(dontRetryForType); } public FailoverPolicy(int numRetries, int sleepBwHostsMilli, Set<Class<E>> dontRetryForTypes) { this.numRetries = numRetries; sleepBetweenHostsMilli = sleepBwHostsMilli; this.dontRetry = dontRetryForTypes; } /** * Determines if a given class is an exception or error that this FailoverPolicy supports retry for. * This is a supplement to the explicit behavior defined in {@link me.prettyprint.cassandra.connection.HConnectionManager}. */ public boolean shouldRetryFor(Class<E> candidate) { Preconditions.checkNotNull(candidate, "Requires a non-null candidate class"); if (dontRetry != null) { return !dontRetry.contains(candidate); } else { return true; } } }