Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix checkstyle issues in com.fauna.client #182

Merged
merged 1 commit into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/main/java/com/fauna/client/BaseFaunaClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public final class BaseFaunaClient extends FaunaClient {
* @param httpClient A Java HTTP client instance.
* @param retryStrategy An implementation of RetryStrategy.
*/
public BaseFaunaClient(FaunaConfig faunaConfig,
HttpClient httpClient, RetryStrategy retryStrategy) {
public BaseFaunaClient(final FaunaConfig faunaConfig,
final HttpClient httpClient, final RetryStrategy retryStrategy) {
super(faunaConfig.getSecret(), faunaConfig.getLogHandler(),
faunaConfig.getStatsCollector());
this.httpClient = httpClient;
Expand All @@ -52,7 +52,7 @@ public BaseFaunaClient(FaunaConfig faunaConfig,
*
* @param faunaConfig The Fauna configuration settings.
*/
public BaseFaunaClient(FaunaConfig faunaConfig) {
public BaseFaunaClient(final FaunaConfig faunaConfig) {
this(faunaConfig, HttpClient.newBuilder().build(),
DEFAULT_RETRY_STRATEGY);
}
Expand Down
126 changes: 75 additions & 51 deletions src/main/java/com/fauna/client/ExponentialBackoffStrategy.java
Original file line number Diff line number Diff line change
@@ -1,88 +1,77 @@
package com.fauna.client;


public class ExponentialBackoffStrategy implements RetryStrategy {
/**
* Implements an exponential backoff strategy for retries.
* The backoff delay increases exponentially with each retry attempt, with optional jitter.
*/
public final class ExponentialBackoffStrategy implements RetryStrategy {
private final float backoffFactor;
private final int maxAttempts;
private final int initialIntervalMillis;
private final int maxBackoffMillis;
private final float jitterFactor;

/**
* Construct an Exponential backoff strategy.
* The basic formula for exponential backoff is `b^(a-1)` where `b` is the backoff factor, and `a` is the retry
* attempt number. So for a backoff factor of 2, you get:
* 2^0=1, 2^1=2, 2^3=4, 2^4=8 ...
* Constructs an Exponential backoff strategy.
*
* @param maxAttempts The maximum amount of retry attempts. Defaults to 3 retry attempts which means
* the client will make a total of 4 requests before giving up.
* @param backoffFactor Defines how quickly the client will back off, default is 2.
* A value of 1 would not backoff (not recommended).
* @param initialIntervalMillis Defines the interval for the first wait. Default is 1000ms.
* @param maxBackoffMillis Set a cap on the delay between requests. The default is 20,000ms
* @param jitterFactor A value between 0 (0%) and 1 (100%) that controls how much to jitter the delay.
* The default is 0.5.
* @param maxAttempts The maximum number of retry attempts. Defaults to 3 retries.
* @param backoffFactor The factor by which the delay will increase. Default is 2.
* @param initialIntervalMillis The interval (in milliseconds) for the first retry attempt. Default is 1000ms.
* @param maxBackoffMillis The maximum delay (in milliseconds) between retries. Default is 20000ms.
* @param jitterFactor A value between 0 and 1 that controls the jitter factor. Default is 0.5.
*/
ExponentialBackoffStrategy(int maxAttempts, float backoffFactor,
int initialIntervalMillis,
int maxBackoffMillis, float jitterFactor) {
ExponentialBackoffStrategy(final int maxAttempts, final float backoffFactor,
final int initialIntervalMillis,
final int maxBackoffMillis, final float jitterFactor) {
this.maxAttempts = maxAttempts;
this.backoffFactor = backoffFactor;
this.initialIntervalMillis = initialIntervalMillis;
this.maxBackoffMillis = maxBackoffMillis;
this.jitterFactor = jitterFactor;

if (jitterFactor < 0.0 || jitterFactor > 1.0) {
throw new IllegalArgumentException(
"Jitter factor must be between 0 and 1.");
throw new IllegalArgumentException("Jitter factor must be between 0 and 1.");
}
if (backoffFactor < 0.0) {
throw new IllegalArgumentException(
"Backoff factor must be positive.");
throw new IllegalArgumentException("Backoff factor must be positive.");
}
if (maxAttempts < 0) {
throw new IllegalArgumentException(
"Max attempts must be a natural number (not negative).");
throw new IllegalArgumentException("Max attempts must be a natural number (not negative).");
}
if (initialIntervalMillis < 0) {
throw new IllegalArgumentException(
"Initial interval must be positive.");
throw new IllegalArgumentException("Initial interval must be positive.");
}
if (maxBackoffMillis < 0) {
throw new IllegalArgumentException("Max backoff must be positive.");
}
}

/**
* Get the % to jitter the backoff, will be a value between 0 and jitterFactor.
* Generates a random jitter percent between 0 and the jitterFactor.
*
* @return A randomly generated value between 0 and jitterFactor.
* @return A random jitter percent.
*/
private double getJitterPercent() {
return Math.random() * jitterFactor;
}

@Override
public boolean canRetry(int retryAttempt) {
public boolean canRetry(final int retryAttempt) {
if (retryAttempt < 0) {
throw new IllegalArgumentException(
"Retry attempt must be a natural number (not negative).");
throw new IllegalArgumentException("Retry attempt must be a natural number (not negative).");
}
return retryAttempt <= maxAttempts;
}

@Override
public int getDelayMillis(int retryAttempt) {
public int getDelayMillis(final int retryAttempt) {
if (retryAttempt < 0) {
throw new IllegalArgumentException(
"Retry attempt must be a natural number (not negative).");
throw new IllegalArgumentException("Retry attempt must be a natural number (not negative).");
} else if (retryAttempt == 0) {
return 0;
} else {
double deterministicBackoff =
Math.pow(this.backoffFactor, retryAttempt - 1);
double calculatedBackoff =
deterministicBackoff * (1 - getJitterPercent()) *
initialIntervalMillis;
double deterministicBackoff = Math.pow(this.backoffFactor, retryAttempt - 1);
double calculatedBackoff = deterministicBackoff * (1 - getJitterPercent()) * initialIntervalMillis;
return (int) Math.min(calculatedBackoff, this.maxBackoffMillis);
}
}
Expand All @@ -92,47 +81,77 @@ public int getMaxRetryAttempts() {
return this.maxAttempts;
}


/**
* Build a new ExponentialBackoffStrategy. This builder only supports setting maxAttempts, because that's the only
* variable that we recommend users change in production. If you need to modify other values for debugging, or other
* purposes, then you can use the constructor directly.
* Builder class for the ExponentialBackoffStrategy.
* Allows fluent configuration of the backoff strategy parameters.
*/
public static class Builder {
private float backoffFactor = 2.0f;
// Results in delay of 1, 2, 4, 8, 16... seconds.
private int maxAttempts = 3; // Limits number of retry attempts.
private int maxAttempts = 3;
private int initialIntervalMillis = 1000;
private int maxBackoffMillis = 20_000;
// A jitterFactor of 0.5, combined with a backoffFactor of 2 ensures that the delay is always increasing.
private float jitterFactor = 0.5f;


public Builder maxAttempts(int maxAttempts) {
/**
* Sets the maximum number of retry attempts.
*
* @param maxAttempts The maximum number of retry attempts.
* @return The current Builder instance.
*/
public Builder maxAttempts(final int maxAttempts) {
this.maxAttempts = maxAttempts;
return this;
}

public Builder backoffFactor(float backoffFactor) {
/**
* Sets the backoff factor.
*
* @param backoffFactor The factor by which the backoff delay increases.
* @return The current Builder instance.
*/
public Builder backoffFactor(final float backoffFactor) {
this.backoffFactor = backoffFactor;
return this;
}

public Builder initialIntervalMillis(int initialIntervalMillis) {
/**
* Sets the initial interval (in milliseconds) for the first retry attempt.
*
* @param initialIntervalMillis The initial interval in milliseconds.
* @return The current Builder instance.
*/
public Builder initialIntervalMillis(final int initialIntervalMillis) {
this.initialIntervalMillis = initialIntervalMillis;
return this;
}

public Builder maxBackoffMillis(int maxBackoffMillis) {
/**
* Sets the maximum backoff (in milliseconds) between retries.
*
* @param maxBackoffMillis The maximum backoff in milliseconds.
* @return The current Builder instance.
*/
public Builder maxBackoffMillis(final int maxBackoffMillis) {
this.maxBackoffMillis = maxBackoffMillis;
return this;
}

public Builder jitterFactor(float jitterFactor) {
/**
* Sets the jitter factor (between 0 and 1) to control how much to jitter the backoff delay.
*
* @param jitterFactor The jitter factor.
* @return The current Builder instance.
*/
public Builder jitterFactor(final float jitterFactor) {
this.jitterFactor = jitterFactor;
return this;
}

/**
* Builds and returns a new ExponentialBackoffStrategy instance.
*
* @return A new ExponentialBackoffStrategy.
*/
public ExponentialBackoffStrategy build() {
return new ExponentialBackoffStrategy(
this.maxAttempts, this.backoffFactor,
Expand All @@ -141,6 +160,11 @@ public ExponentialBackoffStrategy build() {
}
}

/**
* Creates a new Builder instance for ExponentialBackoffStrategy.
*
* @return A new Builder instance.
*/
public static Builder builder() {
return new Builder();
}
Expand Down
17 changes: 10 additions & 7 deletions src/main/java/com/fauna/client/Fauna.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import java.net.http.HttpClient;

public class Fauna {
public final class Fauna {

private Fauna() {
}

/**
* Create a default Fauna client.
Expand All @@ -19,7 +22,7 @@ public static FaunaClient client() {
* @param config Fauna configuration object.
* @return A FaunaClient (or subclass of it).
*/
public static FaunaClient client(FaunaConfig config) {
public static FaunaClient client(final FaunaConfig config) {
if (config == null) {
throw new IllegalArgumentException("FaunaConfig cannot be null.");
}
Expand All @@ -34,8 +37,8 @@ public static FaunaClient client(FaunaConfig config) {
* @param retryStrategy An implementation of RetryStrategy.
* @return A FaunaClient (or subclass of it).
*/
public static FaunaClient client(FaunaConfig config, HttpClient httpClient,
RetryStrategy retryStrategy) {
public static FaunaClient client(final FaunaConfig config, final HttpClient httpClient,
final RetryStrategy retryStrategy) {
if (config == null) {
throw new IllegalArgumentException("FaunaConfig cannot be null.");
}
Expand All @@ -49,7 +52,7 @@ public static FaunaClient client(FaunaConfig config, HttpClient httpClient,
* @param database The name of the database.
* @return A FaunaClient (or subclass of it).
*/
public static FaunaClient scoped(FaunaClient client, String database) {
public static FaunaClient scoped(final FaunaClient client, final String database) {
if (client == null) {
throw new IllegalArgumentException("FaunaClient cannot be null.");
}
Expand All @@ -69,8 +72,8 @@ public static FaunaClient scoped(FaunaClient client, String database) {
* @param role A Fauna role (either built-in or user defined).
* @return A FaunaClient (or subclass of it).
*/
public static FaunaClient scoped(FaunaClient client, String database,
FaunaRole role) {
public static FaunaClient scoped(final FaunaClient client, final String database,
final FaunaRole role) {
if (client == null) {
throw new IllegalArgumentException("FaunaClient cannot be null.");
}
Expand Down
Loading
Loading