Skip to content

Commit

Permalink
Merge pull request #182 from fauna/com.fauna.client-javadocs
Browse files Browse the repository at this point in the history
Fix checkstyle issues in com.fauna.client
  • Loading branch information
pnwpedro authored Nov 12, 2024
2 parents 77b1727 + d5ab787 commit 2cf49bd
Show file tree
Hide file tree
Showing 15 changed files with 576 additions and 260 deletions.
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

0 comments on commit 2cf49bd

Please sign in to comment.