From 1293582ab432047fcc7526931757d5ca509161b4 Mon Sep 17 00:00:00 2001 From: michaelraney Date: Sat, 17 Feb 2024 12:18:07 -0500 Subject: [PATCH] Adding Retry policy for easy consumption Adding retry policy and exponential retry policy. When errors occur do to WriteThrottle, ReadThrottle, or System error, Keyspaces returns Cassandra timeout value. This retry policy helps customers retry these errors which are transient. --- .gitignore | 2 + README.md | 38 +++ ...AmazonKeyspacesExponentialRetryPolicy.java | 244 ++++++++++++++++++ .../policies/AmazonKeyspacesRetryPolicy.java | 197 ++++++++++++++ .../policies/KeyspacesRetryOption.java | 29 +++ ...onKeyspacesExponentialRetryPolicyTest.java | 244 ++++++++++++++++++ .../AmazonKeyspacesRetryPolicyTest.java | 138 ++++++++++ .../policies/KeyspacesRetryOptionTest.java | 37 +++ .../java/software/aws/mcs/auth/TestSigV4.java | 7 +- .../keyspaces-reference-retry-defaults.conf | 40 +++ ...-reference-retry-exponential-defaults.conf | 32 +++ ...keyspaces-reference-retry-exponential.conf | 43 +++ .../resources/keyspaces-reference-retry.conf | 41 +++ 13 files changed, 1090 insertions(+), 2 deletions(-) create mode 100644 src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicy.java create mode 100644 src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicy.java create mode 100644 src/main/java/software/aws/keyspaces/policies/KeyspacesRetryOption.java create mode 100644 src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicyTest.java create mode 100644 src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicyTest.java create mode 100644 src/test/java/software/aws/keyspaces/policies/KeyspacesRetryOptionTest.java create mode 100644 src/test/resources/keyspaces-reference-retry-defaults.conf create mode 100644 src/test/resources/keyspaces-reference-retry-exponential-defaults.conf create mode 100644 src/test/resources/keyspaces-reference-retry-exponential.conf create mode 100644 src/test/resources/keyspaces-reference-retry.conf diff --git a/.gitignore b/.gitignore index c8ee1df..ae62625 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target/ /dependency-reduced-pom.xml +/.idea/ +**/.DS_Store diff --git a/README.md b/README.md index 02d8e2f..b09a294 100644 --- a/README.md +++ b/README.md @@ -171,4 +171,42 @@ The following is an example of this config with an explicit role to be assumed. } } } +``` + +### Additional Helpers + +## Retry Policies +The java driver will attempt to retry idempotent request transparently to the application. If you are seeing NoHostAvailableException when using Amazon Keyspaces, replacing the default retry policy with the ones provided in this repository will be beneficial. + +Implementing a driver retry policy is not a replacement for an application level retry. Users of Apache Cassandra or Amazon Keyspaces should implement an application level retry mechanism for request that satisfy the applications business requirements. + +### AmazonKeyspacesRetryPolicy +The Amazon Keyspaces Retry Policy is an alternative to the DefaultRetryPolicy for the Cassandra Driver. The main difference from the DefaultRetryPolicy, is the AmazonKeyspacesRetryPolicy will retry request a configurable number of times. By default, we take a conservative approach of 3 retry attempts. This driver retry policy will not throw a NoHostAvailableException. Instead, this retry policy will pass back the original exception sent back from the service. + +The following code shows how to include the AmazonKeyspacesRetryPolicy to existing configuration + +``` + advanced.retry-policy { + class = com.aws.ssa.keyspaces.retry.AmazonKeyspacesRetryPolicy + max-attempts = 3 +} +``` +### AmazonKeyspacesExponentialRetryPolicy +In addition to the configurable retry attempts, the Amazon Keyspaces Exponential Retry Policy will add expoential backoff. Inserting an exponentially increasing delay in each retry attempt. +Exponential algorithm with jitter is based on the [following blog](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/). + +The following code shows how to include the AmazonKeyspacesExponentialRetryPolicy to existing configuration. +* max-attempts will define number of retry attempts +* min-wait defines a minimum delay between each retry in ms. +* max-wait defines a upper bound of delay between each retry attempt. +``` +datastax-java-driver { + basic.request.default-idempotence = true + advanced.retry-policy{ + class = com.aws.ssa.keyspaces.retry.AmazonKeyspacesExponentialRetryPolicy + max-attempts = 3 + min-wait = 10 mills + max-wait = 100 mills + } + } ``` \ No newline at end of file diff --git a/src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicy.java b/src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicy.java new file mode 100644 index 0000000..d94182a --- /dev/null +++ b/src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicy.java @@ -0,0 +1,244 @@ +package software.aws.keyspaces.policies; + +import com.datastax.oss.driver.api.core.ConsistencyLevel; +import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; +import com.datastax.oss.driver.api.core.context.DriverContext; +import com.datastax.oss.driver.api.core.retry.RetryDecision; +import com.datastax.oss.driver.api.core.retry.RetryPolicy; +import com.datastax.oss.driver.api.core.servererrors.CoordinatorException; +import com.datastax.oss.driver.api.core.servererrors.ReadTimeoutException; +import com.datastax.oss.driver.api.core.servererrors.WriteTimeoutException; +import com.datastax.oss.driver.api.core.servererrors.WriteType; +import com.datastax.oss.driver.api.core.session.Request; +import com.datastax.oss.driver.internal.core.retry.DefaultRetryPolicy; +import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting; +import com.datastax.oss.driver.shaded.guava.common.util.concurrent.Uninterruptibles; +import edu.umd.cs.findbugs.annotations.NonNull; +import net.jcip.annotations.ThreadSafe; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + + +/** + * This is a conservative retry policy adapted for the Amazon Keyspaces Service. + * It allows for a configurable number of attempts, but by default the number of attempts is {@value software.aws.keyspaces.policies.KeyspacesRetryOption#DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS} + *

+ * This policy will either reattempt request on the same host or rethrow the exception to the calling thread. The main difference between + * this policy from the original {@link DefaultRetryPolicy} is that the {@link AmazonKeyspacesExponentialRetryPolicy} will call {@link RetryDecision#RETRY_SAME} instead of {@link RetryDecision#RETRY_NEXT} + *

+ * In Amazon Keyspaces, it's likely that {@link WriteTimeoutException} or {@link ReadTimeoutException} is the result of exceeding current table + * capacity. Learn more about Amazon Keyspaces capacity here: @see Amazon Keyspaces CapacityModes. + * In most cases you should allow for small number of retries, and handle the exception in your application threads. + * + *

To activate this policy, modify the {@code advanced.retry-policy} section in the driver + * configuration, for example: + * + *

+ * datastax-java-driver {
+ *    basic.request.default-idempotence = true
+ *    advanced.retry-policy{
+ *      class =  com.aws.ssa.keyspaces.retry.AmazonKeyspacesExponentialRetryPolicy
+ *      max-attempts = 3
+ *      min-wait = 10 mills
+ *      max-wait = 100 mills
+ *    }
+ * }
+ * 
+ */ + +@ThreadSafe +public class AmazonKeyspacesExponentialRetryPolicy implements RetryPolicy { + + + private static final Logger LOG = LoggerFactory.getLogger(AmazonKeyspacesExponentialRetryPolicy.class); + @VisibleForTesting + public static final String RETRYING_ON_READ_TIMEOUT = "[{}] Retrying on read timeout on same host (consistency: {}, required responses: {}, received responses: {}, data retrieved: {}, retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_WRITE_TIMEOUT = "[{}] Retrying on write timeout on same host (consistency: {}, write type: {}, required acknowledgments: {}, received acknowledgments: {}, retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_UNAVAILABLE = "[{}] Retrying on unavailable exception on next host (consistency: {}, required replica: {}, alive replica: {}, retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_ABORTED = "[{}] Retrying on aborted request on next host (retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_ERROR = "[{}] Retrying on node error on next host (retries: {})"; + + private final String logPrefix; + + private final Integer maxRetryCount; + private final Long minWaitTime; + private final Long maxWaitTime; + + //private final Integer maxTimeToWait; + public AmazonKeyspacesExponentialRetryPolicy(DriverContext context) { + this(context, context.getConfig().getDefaultProfile().getName()); + } + + public AmazonKeyspacesExponentialRetryPolicy(DriverContext context, Integer maxRetryCount) { + this(context, context.getConfig().getDefaultProfile().getName(), maxRetryCount, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MIN_WAIT, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_WAIT); + } + + public AmazonKeyspacesExponentialRetryPolicy(DriverContext context, String profileName) { + this( + context, + profileName, + context.getConfig().getProfile(profileName).getInt(software.aws.keyspaces.policies.KeyspacesRetryOption.KEYSPACES_RETRY_MAX_ATTEMPTS, software.aws.keyspaces.policies.KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS), + context.getConfig().getProfile(profileName).getDuration(software.aws.keyspaces.policies.KeyspacesRetryOption.KEYSPACES_RETRY_MIN_WAIT, software.aws.keyspaces.policies.KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MIN_WAIT), + context.getConfig().getProfile(profileName).getDuration(software.aws.keyspaces.policies.KeyspacesRetryOption.KEYSPACES_RETRY_MAX_WAIT, software.aws.keyspaces.policies.KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_WAIT)); + } + public AmazonKeyspacesExponentialRetryPolicy(DriverContext context, Integer maxRetryCount, Duration minWaitTime, Duration maxWaitTime) { + this(context, context.getConfig().getDefaultProfile().getName(), maxRetryCount, minWaitTime, maxWaitTime); + } + public AmazonKeyspacesExponentialRetryPolicy(DriverContext context, String profileName, Integer maxRetryCount, Duration minWaitTime, Duration maxWaitTime) { + + this.maxRetryCount = maxRetryCount; + this.minWaitTime = minWaitTime.toMillis(); + this.maxWaitTime = maxWaitTime.toMillis(); + + this.logPrefix = (context != null ? context.getSessionName() : null) + "|" + profileName; + } + + + protected RetryDecision determineRetryDecision(int retryCount) { + + if (retryCount < maxRetryCount) { + timeToWait(retryCount); + + return RetryDecision.RETRY_SAME; + } else { + return RetryDecision.RETHROW; + + + } + } + /*** https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ + jitter (from retry count to exponential 2^retry count) + rand(0, 2^1) 0-2 ms + rand(1, 2^2) 1-4 ms + rand(2, 2^3) 4-9 ms + rand(3, 2^4) 6-16 ms + rand(4, 2^5) 8-32 ms + rand(5, 2^6) 10-64 ms + rand(9, 2^10) 18-1024 //one second ***/ + protected void timeToWait(int retryCount){ + + long exponentialWaitWithJitter = ThreadLocalRandom.current().nextInt(retryCount*2, Double.valueOf(Math.pow(2d, Integer.valueOf(retryCount+1).doubleValue())).intValue()); + + long timeToWaitCalculation = Math.max(minWaitTime, exponentialWaitWithJitter); + + long timeToWaitFinal = Math.min(maxWaitTime, timeToWaitCalculation); + + Uninterruptibles.sleepUninterruptibly(timeToWaitFinal, TimeUnit.MILLISECONDS); + } + + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + * + *

Otherwise, the exception is rethrown. + */ + @Override + public RetryDecision onReadTimeout( + @NonNull Request request, + @NonNull ConsistencyLevel cl, + int blockFor, + int received, + boolean dataPresent, + int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_READ_TIMEOUT, logPrefix, cl, blockFor, received, false, retryCount); + + return decision; + + } + + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + * + *

Otherwise, the exception is rethrown. + */ + @Override + public RetryDecision onWriteTimeout( + @NonNull Request request, + @NonNull ConsistencyLevel cl, + @NonNull WriteType writeType, + int blockFor, + int received, + int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_WRITE_TIMEOUT, logPrefix, cl, blockFor, received, false, retryCount); + + return decision; + } + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + * + *

Otherwise, the exception is rethrown. + */ + @Override + public RetryDecision onUnavailable( + @NonNull Request request, + @NonNull ConsistencyLevel cl, + int required, + int alive, + int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_UNAVAILABLE, logPrefix, cl, required, alive, retryCount); + + return decision; + } + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + */ + @Override + public RetryDecision onRequestAborted( + @NonNull Request request, @NonNull Throwable error, int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_ABORTED, logPrefix, retryCount, error); + + return decision; + } + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + */ + @Override + public RetryDecision onErrorResponse( + @NonNull Request request, @NonNull CoordinatorException error, int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_ERROR, logPrefix, retryCount, error); + + return decision; + } + + @Override + public void close() { + // nothing to do + } +} \ No newline at end of file diff --git a/src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicy.java b/src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicy.java new file mode 100644 index 0000000..7d1d11b --- /dev/null +++ b/src/main/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicy.java @@ -0,0 +1,197 @@ +package software.aws.keyspaces.policies; + +import com.datastax.oss.driver.api.core.ConsistencyLevel; +import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; +import com.datastax.oss.driver.api.core.context.DriverContext; +import com.datastax.oss.driver.api.core.retry.RetryDecision; +import com.datastax.oss.driver.api.core.retry.RetryPolicy; +import com.datastax.oss.driver.api.core.servererrors.CoordinatorException; +import com.datastax.oss.driver.api.core.servererrors.ReadTimeoutException; +import com.datastax.oss.driver.api.core.servererrors.WriteTimeoutException; +import com.datastax.oss.driver.api.core.servererrors.WriteType; +import com.datastax.oss.driver.api.core.session.Request; +import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting; +import edu.umd.cs.findbugs.annotations.NonNull; +import net.jcip.annotations.ThreadSafe; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * This is a conservative retry policy adapted for the Amazon Keyspaces Service. + * It allows for a configurable number of attempts, but by default the number of attempts is {@value KeyspacesRetryOption#DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS} + *

+ * This policy will either reattempt request on the same host or rethrow the exception to the calling thread. The main difference between + * this policy from the original {@link com.datastax.oss.driver.internal.core.retry.DefaultRetryPolicy} is that the {@link AmazonKeyspacesRetryPolicy} will call {@link RetryDecision#RETRY_SAME} instead of {@link RetryDecision#RETRY_NEXT} + *

+ * In Amazon Keyspaces, it's likely that {@link WriteTimeoutException} or {@link ReadTimeoutException} is the result of exceeding current table + * capacity. Learn more about Amazon Keyspaces capacity here: @see Amazon Keyspaces CapacityModes. + * In most cases you should allow for small number of retries, and handle the exception in your application threads. + * + *

To activate this policy, modify the {@code advanced.retry-policy} section in the driver + * configuration, for example: + * + *

+ * datastax-java-driver {
+ *   advanced.retry-policy {
+ *     class = com.aws.ssa.keyspaces.retry.AmazonKeyspacesRetryPolicy
+ *     max-attempts = 2
+ *   }
+ * }
+ * 
+ */ + +@ThreadSafe +public class AmazonKeyspacesRetryPolicy implements RetryPolicy { + + private static final Logger LOG = LoggerFactory.getLogger(AmazonKeyspacesRetryPolicy.class); + @VisibleForTesting + public static final String RETRYING_ON_READ_TIMEOUT = "[{}] Retrying on read timeout on same host (consistency: {}, required responses: {}, received responses: {}, data retrieved: {}, retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_WRITE_TIMEOUT = "[{}] Retrying on write timeout on same host (consistency: {}, write type: {}, required acknowledgments: {}, received acknowledgments: {}, retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_UNAVAILABLE = "[{}] Retrying on unavailable exception on next host (consistency: {}, required replica: {}, alive replica: {}, retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_ABORTED = "[{}] Retrying on aborted request on next host (retries: {})"; + @VisibleForTesting + public static final String RETRYING_ON_ERROR = "[{}] Retrying on node error on next host (retries: {})"; + + private final String logPrefix; + + private final Integer maxRetryCount; + + public AmazonKeyspacesRetryPolicy(DriverContext context) { + this(context, context.getConfig().getDefaultProfile().getName()); + } + public AmazonKeyspacesRetryPolicy(DriverContext context, Integer maxRetryCount) { + this(context, context.getConfig().getDefaultProfile().getName(), maxRetryCount); + } + public AmazonKeyspacesRetryPolicy(DriverContext context, String profileName) { + this( + context, + profileName, + context.getConfig() + .getProfile(profileName) + .getInt(KeyspacesRetryOption.KEYSPACES_RETRY_MAX_ATTEMPTS, + KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS)); + } + + public AmazonKeyspacesRetryPolicy(DriverContext context, String profileName, Integer maxRetryCount) { + this.maxRetryCount = maxRetryCount; + + this.logPrefix = (context != null ? context.getSessionName() : null) + "|" + profileName; + } + + protected RetryDecision determineRetryDecision(int retryCount) { + if (retryCount < maxRetryCount) { + return RetryDecision.RETRY_SAME; + } else { + return RetryDecision.RETHROW; + } + } + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + * + *

Otherwise, the exception is rethrown. + */ + @Override + public RetryDecision onReadTimeout( + @NonNull Request request, + @NonNull ConsistencyLevel cl, + int blockFor, + int received, + boolean dataPresent, + int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_READ_TIMEOUT, logPrefix, cl, blockFor, received, false, retryCount); + + return decision; + + } + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + * + *

Otherwise, the exception is rethrown. + */ + @Override + public RetryDecision onWriteTimeout( + @NonNull Request request, + @NonNull ConsistencyLevel cl, + @NonNull WriteType writeType, + int blockFor, + int received, + int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_WRITE_TIMEOUT, logPrefix, cl, blockFor, received, false, retryCount); + + return decision; + } + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + * + *

Otherwise, the exception is rethrown. + */ + @Override + public RetryDecision onUnavailable( + @NonNull Request request, + @NonNull ConsistencyLevel cl, + int required, + int alive, + int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_UNAVAILABLE, logPrefix, cl, required, alive, retryCount); + + return decision; + } + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + */ + @Override + public RetryDecision onRequestAborted( + @NonNull Request request, @NonNull Throwable error, int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_ABORTED, logPrefix, retryCount, error); + + return decision; + } + + /** + * {@inheritDoc} + * + *

This implementation triggers a maximum of configured retry (to the same connection) + */ + @Override + public RetryDecision onErrorResponse( + @NonNull Request request, @NonNull CoordinatorException error, int retryCount) { + + RetryDecision decision = determineRetryDecision(retryCount); + + LOG.trace(RETRYING_ON_ERROR, logPrefix, retryCount, error); + + return decision; + } + + @Override + public void close() { + // nothing to do + } +} \ No newline at end of file diff --git a/src/main/java/software/aws/keyspaces/policies/KeyspacesRetryOption.java b/src/main/java/software/aws/keyspaces/policies/KeyspacesRetryOption.java new file mode 100644 index 0000000..7c8bc6b --- /dev/null +++ b/src/main/java/software/aws/keyspaces/policies/KeyspacesRetryOption.java @@ -0,0 +1,29 @@ +package software.aws.keyspaces.policies; + +import com.datastax.oss.driver.api.core.config.DriverOption; + +import java.time.Duration; + +public enum KeyspacesRetryOption implements DriverOption { + + + KEYSPACES_RETRY_MAX_ATTEMPTS("advanced.retry-policy.max-attempts"), + KEYSPACES_RETRY_MIN_WAIT("advanced.retry-policy.min-wait"), + KEYSPACES_RETRY_MAX_WAIT("advanced.retry-policy.max-wait"); + + public static final Integer DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS = 3; + public static final Duration DEFAULT_KEYSPACES_RETRY_MIN_WAIT = Duration.ofMillis(10); + public static final Duration DEFAULT_KEYSPACES_RETRY_MAX_WAIT = Duration.ofMillis(50); + + private final String path; + + KeyspacesRetryOption(String path) { + this.path = path; + } + + @Override + public String getPath() { + return path; + } + +} diff --git a/src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicyTest.java b/src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicyTest.java new file mode 100644 index 0000000..baffba8 --- /dev/null +++ b/src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesExponentialRetryPolicyTest.java @@ -0,0 +1,244 @@ +package software.aws.keyspaces.policies; + +import com.datastax.oss.driver.api.core.ConsistencyLevel; +import com.datastax.oss.driver.api.core.config.DriverConfigLoader; +import com.datastax.oss.driver.api.core.context.DriverContext; +import com.datastax.oss.driver.api.core.retry.RetryDecision; +import com.datastax.oss.driver.api.core.servererrors.WriteFailureException; +import com.datastax.oss.driver.api.core.servererrors.WriteType; +import com.datastax.oss.driver.api.core.session.ProgrammaticArguments; +import com.datastax.oss.driver.internal.core.config.typesafe.DefaultProgrammaticDriverConfigLoaderBuilder; +import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; +import com.datastax.oss.driver.shaded.guava.common.base.Stopwatch; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Duration; + +public class AmazonKeyspacesExponentialRetryPolicyTest { + + @Test + public void determineRetryDecisionExceed() { + + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3, Duration.ofMillis(10), Duration.ofMillis(50)); + + assertEquals(RetryDecision.RETHROW, st.determineRetryDecision(4)); + + } + + @Test + public void determineRetryTimeToMinWhenRetry() { + + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 1, Duration.ofMillis(10), Duration.ofMillis(50)); + + Stopwatch stopwatch = Stopwatch.createStarted(); + + st.determineRetryDecision(0); + + stopwatch.stop(); + + long millsObserved = stopwatch.elapsed().toMillis(); + + assertTrue(millsObserved > 1 && millsObserved < 21); + + } + @Test + public void determineRetryTimeToMinWhenNotRetry() { + + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + + AmazonKeyspacesExponentialRetryPolicy st= new AmazonKeyspacesExponentialRetryPolicy(context, 0, Duration.ofMillis(10), Duration.ofMillis(50)); + + Stopwatch stopwatch = Stopwatch.createStarted(); + + st.determineRetryDecision(0); + + stopwatch.stop(); + + long millsObserved = stopwatch.elapsed().toMillis(); + + System.out.println(millsObserved); + + assertTrue(millsObserved >= 0 && millsObserved < 5); + + } + @Test + public void determineRetryTimeToMinWait() { + + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + + Integer retryAttempt = 0; + Duration min = Duration.ofMillis(10); + Duration max = Duration.ofMillis(50); + Duration buffer = Duration.ofMillis(5); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, retryAttempt+1, min, max); + + Stopwatch stopwatch = Stopwatch.createStarted(); + + st.timeToWait(retryAttempt); + + stopwatch.stop(); + + long millsObserved = stopwatch.elapsed().toMillis(); + + assertTrue( millsObserved >= min.toMillis() && millsObserved < min.toMillis() + buffer.toMillis(), String.format("Asset %s", millsObserved)); + } + @Test + public void determineRetryTimeToWaitMid() { + + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + + Integer retryAttempt = 5; + Duration min = Duration.ofMillis(10); + Duration max = Duration.ofMillis(100); + Duration buffer = Duration.ofMillis(5); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, retryAttempt+1, min, max); + + Stopwatch stopwatch = Stopwatch.createStarted(); + + st.timeToWait(retryAttempt); + + stopwatch.stop(); + + long millsObserved = stopwatch.elapsed().toMillis(); + + //10 min, 5 retry + 5 buffer , 10 min, 2^5 expo + 5 buffer + assertTrue(millsObserved >= min.toMillis() && millsObserved < (Math.pow(2, retryAttempt+1)+ buffer.toMillis()), String.format("millsObserved: %d",millsObserved)); + + } + @Test + public void determineRetryTimeToWaitMax() { + + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + + Integer retryAttempt = 100; + Duration min = Duration.ofMillis(10); + Duration max = Duration.ofMillis(50); + Duration buffer = Duration.ofMillis(5); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, retryAttempt+1, min, max); + + Stopwatch stopwatch = Stopwatch.createStarted(); + + st.timeToWait(retryAttempt); + + stopwatch.stop(); + + long millsObserved = stopwatch.elapsed().toMillis(); + + //slightly greater than max + assertTrue(millsObserved >= max.toMillis() && millsObserved < max.toMillis()+buffer.toMillis(), String.format("millsObserved: %d",millsObserved)); + + } + + @Test + public void determineRetryDecisionMin() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.determineRetryDecision(0)); + + } + + @Test + public void determineRetryDecisionMid() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.determineRetryDecision(1)); + + } + + @Test + public void onWriteTimeout() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onWriteTimeout(null, ConsistencyLevel.LOCAL_QUORUM, WriteType.SIMPLE, 2, 0, 1)); + + } + + @Test + public void onWriteTimeoutExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETHROW, st.onWriteTimeout(null, ConsistencyLevel.LOCAL_QUORUM, WriteType.SIMPLE, 2, 0, 4)); + + } + + @Test + public void onReadTimeout() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onReadTimeout(null, ConsistencyLevel.LOCAL_QUORUM, 2, 0, false, 1)); + + } + + @Test + public void onReadTimeoutExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETHROW, st.onReadTimeout(null, ConsistencyLevel.LOCAL_QUORUM, 2, 0, false, 4)); + + } + + @Test + public void oneError() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onErrorResponse(null, new WriteFailureException(null, ConsistencyLevel.LOCAL_QUORUM, 0, 2, WriteType.SIMPLE, 1, null), 2)); + + } + + @Test + public void oneErrorExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + + assertEquals(RetryDecision.RETHROW, st.onErrorResponse(null, new WriteFailureException(null, ConsistencyLevel.LOCAL_QUORUM, 0, 2, WriteType.SIMPLE, 1, null), 4)); + + } + + @Test + public void onUnavailable() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onUnavailable(null, ConsistencyLevel.LOCAL_QUORUM, 1, 1, 2)); + + } + + @Test + public void onUnavailableExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesExponentialRetryPolicy st = new AmazonKeyspacesExponentialRetryPolicy(context, 3); + + + assertEquals(RetryDecision.RETHROW, st.onUnavailable(null, ConsistencyLevel.LOCAL_QUORUM, 1, 1, 4)); + } + + @Test + public void testConfig() { + assertEquals(5, DriverConfigLoader.fromClasspath("keyspaces-reference-retry-exponential.conf").getInitialConfig().getDefaultProfile().getInt(KeyspacesRetryOption.KEYSPACES_RETRY_MAX_ATTEMPTS, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS)); + assertEquals(20, DriverConfigLoader.fromClasspath("keyspaces-reference-retry-exponential.conf").getInitialConfig().getDefaultProfile().getDuration(KeyspacesRetryOption.KEYSPACES_RETRY_MIN_WAIT, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MIN_WAIT).toMillis()); + assertEquals(100, DriverConfigLoader.fromClasspath("keyspaces-reference-retry-exponential.conf").getInitialConfig().getDefaultProfile().getDuration(KeyspacesRetryOption.KEYSPACES_RETRY_MAX_WAIT, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_WAIT).toMillis()); + } + @Test + public void testConfigDefaults() { + assertEquals(3, DriverConfigLoader.fromClasspath("keyspaces-reference-retry-exponential-defaults.conf").getInitialConfig().getDefaultProfile().getInt(KeyspacesRetryOption.KEYSPACES_RETRY_MAX_ATTEMPTS, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS)); + assertEquals(10, DriverConfigLoader.fromClasspath("keyspaces-reference-retry-exponential-defaults.conf").getInitialConfig().getDefaultProfile().getDuration(KeyspacesRetryOption.KEYSPACES_RETRY_MIN_WAIT, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MIN_WAIT).toMillis()); + assertEquals(50, DriverConfigLoader.fromClasspath("keyspaces-reference-retry-exponential-defaults.conf").getInitialConfig().getDefaultProfile().getDuration(KeyspacesRetryOption.KEYSPACES_RETRY_MAX_WAIT, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_WAIT).toMillis()); + } + +} + diff --git a/src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicyTest.java b/src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicyTest.java new file mode 100644 index 0000000..128fa42 --- /dev/null +++ b/src/test/java/software/aws/keyspaces/policies/AmazonKeyspacesRetryPolicyTest.java @@ -0,0 +1,138 @@ +package software.aws.keyspaces.policies; + +import com.datastax.oss.driver.api.core.ConsistencyLevel; +import com.datastax.oss.driver.api.core.config.DriverConfigLoader; +import com.datastax.oss.driver.api.core.context.DriverContext; +import com.datastax.oss.driver.api.core.retry.RetryDecision; +import com.datastax.oss.driver.api.core.servererrors.WriteFailureException; +import com.datastax.oss.driver.api.core.servererrors.WriteType; +import com.datastax.oss.driver.api.core.session.ProgrammaticArguments; +import com.datastax.oss.driver.internal.core.config.typesafe.DefaultProgrammaticDriverConfigLoaderBuilder; +import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class AmazonKeyspacesRetryPolicyTest { + + @Test + public void determineRetryDecisionExceed() { + + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETHROW, st.determineRetryDecision(4)); + + } + + @Test + public void determineRetryDecisionMin() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.determineRetryDecision(0)); + + } + + @Test + public void determineRetryDecisionMid() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.determineRetryDecision(1)); + + } + @Test + public void determinRetryFalse() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + + assertEquals(RetryDecision.RETHROW, st.onUnavailable(null, ConsistencyLevel.LOCAL_QUORUM, 1, 1, 4)); + } + + @Test + public void onWriteTimeout() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onWriteTimeout(null, ConsistencyLevel.LOCAL_QUORUM, WriteType.SIMPLE, 2, 0, 1)); + + } + + @Test + public void onWriteTimeoutExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETHROW, st.onWriteTimeout(null, ConsistencyLevel.LOCAL_QUORUM, WriteType.SIMPLE, 2, 0, 4)); + + } + + @Test + public void onReadTimeout() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onReadTimeout(null, ConsistencyLevel.LOCAL_QUORUM, 2, 0, false, 1)); + + } + + @Test + public void onReadTimeoutExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETHROW, st.onReadTimeout(null, ConsistencyLevel.LOCAL_QUORUM, 2, 0, false, 4)); + + } + + @Test + public void oneError() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onErrorResponse(null, new WriteFailureException(null, ConsistencyLevel.LOCAL_QUORUM, 0, 2, WriteType.SIMPLE, 1, null), 2)); + + } + + @Test + public void oneErrorExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + + assertEquals(RetryDecision.RETHROW, st.onErrorResponse(null, new WriteFailureException(null, ConsistencyLevel.LOCAL_QUORUM, 0, 2, WriteType.SIMPLE, 1, null), 4)); + + } + + @Test + public void onUnavailable() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + assertEquals(RetryDecision.RETRY_SAME, st.onUnavailable(null, ConsistencyLevel.LOCAL_QUORUM, 1, 1, 2)); + + } + + @Test + public void onUnavailableExceed() { + DriverContext context = new DefaultDriverContext(new DefaultProgrammaticDriverConfigLoaderBuilder().build(), ProgrammaticArguments.builder().build()); + AmazonKeyspacesRetryPolicy st = new AmazonKeyspacesRetryPolicy(context, 3); + + + assertEquals(RetryDecision.RETHROW, st.onUnavailable(null, ConsistencyLevel.LOCAL_QUORUM, 1, 1, 4)); + } + + @Test + public void testConfig() { + assertEquals(5, DriverConfigLoader.fromClasspath("keyspaces-reference-retry.conf").getInitialConfig().getDefaultProfile().getInt(KeyspacesRetryOption.KEYSPACES_RETRY_MAX_ATTEMPTS, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS)); + } + @Test + public void testDefaultConfig() { + assertEquals(3, DriverConfigLoader.fromClasspath("keyspaces-reference-retry-defaults.conf").getInitialConfig().getDefaultProfile().getInt(KeyspacesRetryOption.KEYSPACES_RETRY_MAX_ATTEMPTS, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS)); + } + +} + diff --git a/src/test/java/software/aws/keyspaces/policies/KeyspacesRetryOptionTest.java b/src/test/java/software/aws/keyspaces/policies/KeyspacesRetryOptionTest.java new file mode 100644 index 0000000..84436f6 --- /dev/null +++ b/src/test/java/software/aws/keyspaces/policies/KeyspacesRetryOptionTest.java @@ -0,0 +1,37 @@ +package software.aws.keyspaces.policies; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class KeyspacesRetryOptionTest { + + @Test + public void testPathMethod() { + assertEquals("advanced.retry-policy.max-attempts", KeyspacesRetryOption.KEYSPACES_RETRY_MAX_ATTEMPTS.getPath()); + } + + @Test + public void testDefaults() { + assertEquals(3, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_ATTEMPTS); + } + + @Test + public void testMinWaitPathMethod() { + assertEquals("advanced.retry-policy.min-wait", KeyspacesRetryOption.KEYSPACES_RETRY_MIN_WAIT.getPath()); + } + + @Test + public void testMinWaitDefaults() { + assertEquals(10, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MIN_WAIT.toMillis()); + } + + @Test + public void testMaxWaitPathMethod() { + assertEquals("advanced.retry-policy.max-wait", KeyspacesRetryOption.KEYSPACES_RETRY_MAX_WAIT.getPath()); + } + + @Test + public void testMaxWaitDefaults() { + assertEquals(50, KeyspacesRetryOption.DEFAULT_KEYSPACES_RETRY_MAX_WAIT.toMillis()); + } +} diff --git a/src/test/java/software/aws/mcs/auth/TestSigV4.java b/src/test/java/software/aws/mcs/auth/TestSigV4.java index 3c82e5c..529914c 100644 --- a/src/test/java/software/aws/mcs/auth/TestSigV4.java +++ b/src/test/java/software/aws/mcs/auth/TestSigV4.java @@ -29,7 +29,7 @@ import com.datastax.oss.driver.api.core.cql.Row; public class TestSigV4 { - static String[] DEFAULT_CONTACT_POINTS = {"127.0.0.1:9042"}; + static String[] DEFAULT_CONTACT_POINTS = {"cassandra.us-east-1.amazonaws.com"}; public static void main(String[] args) throws Exception { String[] contactPointsRaw = DEFAULT_CONTACT_POINTS; @@ -58,9 +58,12 @@ public static void main(String[] args) throws Exception { .addContactPoints(contactPoints) .withAuthProvider(new SigV4AuthProvider()) .withSslContext(SSLContext.getDefault()) - .withLocalDatacenter("us-west-2") + .withLocalDatacenter("us-east-1") .build()) { + int totalConnection =session.getMetadata().getNodes().values().stream().mapToInt(oneNode->oneNode.getOpenConnections()).sum(); + + System.out.println(totalConnection); // We use execute to send a query to Cassandra. This returns a ResultSet, which is essentially a collection // of Row objects. ResultSet rs = session.execute("select release_version from system.local"); diff --git a/src/test/resources/keyspaces-reference-retry-defaults.conf b/src/test/resources/keyspaces-reference-retry-defaults.conf new file mode 100644 index 0000000..d8fafba --- /dev/null +++ b/src/test/resources/keyspaces-reference-retry-defaults.conf @@ -0,0 +1,40 @@ + +datastax-java-driver { + basic.request.consistency = "LOCAL_QUORUM" + basic.contact-points = [ "cassandra.ap-south-1.amazonaws.com:9142"] + + advanced.reconnect-on-init = true + + basic.load-balancing-policy { + local-datacenter = "ap-south-1" + } + basic.request.timeout = 10 seconds + + basic.request.default-idempotence = true + advanced.retry-policy{ + class = com.aws.ssa.keyspaces.retry.AmazonKeyspacesRetryPolicy + } + advanced.auth-provider = { + class = software.aws.mcs.auth.SigV4AuthProvider + aws-region = ap-south-1 + } + + #advanced.auth-provider{ + # class = PlainTextAuthProvider + # username = "mike-at-102" + # password = "fakepassword" + #} + + + + advanced.ssl-engine-factory { + class = DefaultSslEngineFactory + #truststore-path = "/Users/user/.cassandra/cassandra_truststore.jks" + #truststore-password = "amazon" + hostname-validation = false + } + + advanced.connection.pool.local.size = 2 + + +} diff --git a/src/test/resources/keyspaces-reference-retry-exponential-defaults.conf b/src/test/resources/keyspaces-reference-retry-exponential-defaults.conf new file mode 100644 index 0000000..1f7a86a --- /dev/null +++ b/src/test/resources/keyspaces-reference-retry-exponential-defaults.conf @@ -0,0 +1,32 @@ + +datastax-java-driver { + basic.request.consistency = "LOCAL_QUORUM" + basic.contact-points = [ "cassandra.ap-south-1.amazonaws.com:9142"] + + advanced.reconnect-on-init = true + + basic.load-balancing-policy { + local-datacenter = "ap-south-1" + } + basic.request.timeout = 10 seconds + + basic.request.default-idempotence = true + advanced.retry-policy{ + class = com.aws.ssa.keyspaces.retry.AmazonKeyspacesExponentialRetryPolicy + } + advanced.auth-provider = { + class = software.aws.mcs.auth.SigV4AuthProvider + aws-region = ap-south-1 + } + + advanced.ssl-engine-factory { + class = DefaultSslEngineFactory + #truststore-path = "/Users/user/.cassandra/cassandra_truststore.jks" + #truststore-password = "amazon" + hostname-validation = false + } + + advanced.connection.pool.local.size = 2 + + +} diff --git a/src/test/resources/keyspaces-reference-retry-exponential.conf b/src/test/resources/keyspaces-reference-retry-exponential.conf new file mode 100644 index 0000000..f0907f1 --- /dev/null +++ b/src/test/resources/keyspaces-reference-retry-exponential.conf @@ -0,0 +1,43 @@ + +datastax-java-driver { + basic.request.consistency = "LOCAL_QUORUM" + basic.contact-points = [ "cassandra.ap-south-1.amazonaws.com:9142"] + + advanced.reconnect-on-init = true + + basic.load-balancing-policy { + local-datacenter = "ap-south-1" + } + basic.request.timeout = 10 seconds + + basic.request.default-idempotence = true + advanced.retry-policy{ + class = com.aws.ssa.keyspaces.retry.AmazonKeyspacesExponentialRetryPolicy + max-attempts = 5 + min-wait = 20 ms + max-wait = 100 ms + } + advanced.auth-provider = { + class = software.aws.mcs.auth.SigV4AuthProvider + aws-region = ap-south-1 + } + + #advanced.auth-provider{ + # class = PlainTextAuthProvider + # username = "mike-at-102" + # password = "fakepassword" + #} + + + + advanced.ssl-engine-factory { + class = DefaultSslEngineFactory + #truststore-path = "/Users/user/.cassandra/cassandra_truststore.jks" + #truststore-password = "amazon" + hostname-validation = false + } + + advanced.connection.pool.local.size = 2 + + +} diff --git a/src/test/resources/keyspaces-reference-retry.conf b/src/test/resources/keyspaces-reference-retry.conf new file mode 100644 index 0000000..67bb1dc --- /dev/null +++ b/src/test/resources/keyspaces-reference-retry.conf @@ -0,0 +1,41 @@ + +datastax-java-driver { + basic.request.consistency = "LOCAL_QUORUM" + basic.contact-points = [ "cassandra.ap-south-1.amazonaws.com:9142"] + + advanced.reconnect-on-init = true + + basic.load-balancing-policy { + local-datacenter = "ap-south-1" + } + basic.request.timeout = 10 seconds + + basic.request.default-idempotence = true + advanced.retry-policy{ + class = com.aws.ssa.keyspaces.retry.AmazonKeyspacesRetryPolicy + max-attempts = 5 + } + advanced.auth-provider = { + class = software.aws.mcs.auth.SigV4AuthProvider + aws-region = ap-south-1 + } + + #advanced.auth-provider{ + # class = PlainTextAuthProvider + # username = "mike-at-102" + # password = "fakepassword" + #} + + + + advanced.ssl-engine-factory { + class = DefaultSslEngineFactory + #truststore-path = "/Users/user/.cassandra/cassandra_truststore.jks" + #truststore-password = "amazon" + hostname-validation = false + } + + advanced.connection.pool.local.size = 2 + + +}