Skip to content

Java: move BackoffStrategy configuration to BaseConfiguration + Added Jitter param #3783

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

Merged
merged 6 commits into from
May 27, 2025
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
2 changes: 2 additions & 0 deletions java/client/src/main/java/glide/api/GlideClusterClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ public class GlideClusterClient extends BaseClient
* <code>true</code>, the client will establish secure connections using TLS.
* <li><b>Pub/Sub Subscriptions</b>: Any channels or patterns specified in {@link
* ClusterSubscriptionConfiguration} will be subscribed to upon connection.
* <li><b>Reconnection Strategy</b>: The {@link BackoffStrategy} settings define how the
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think ab it

* client will attempt to reconnect in case of disconnections.
* </ul>
*
* @example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@

/**
* Represents the strategy used to determine how and when to reconnect, in case of connection
* failures. The time between attempts grows exponentially, to the formula <code>rand(0 ... factor *
* (exponentBase ^ N))</code>, where <code>N</code> is the number of failed attempts.
* failures. The time between attempts grows exponentially, following the formula <code>
* rand(0 ... factor *
* (exponentBase ^ N))</code>, where <code>N</code> is the number of failed attempts, and <code>
* rand(...)</code> applies a jitter of up to <code>jitterPercent</code>% to introduce randomness
* and reduce retry storms.
*
* <p>Once the maximum value is reached, that will remain the time between retry attempts until a
* reconnect attempt is successful. The client will attempt to reconnect indefinitely.
Expand All @@ -20,6 +23,7 @@
* .numOfRetries(5)
* .exponentBase(2)
* .factor(3)
* .jitterPercent(20)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix doc above

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

python

* .build()
* }</pre>
*/
Expand All @@ -39,4 +43,7 @@ public class BackoffStrategy {

/** The exponent base configured for the strategy. */
@NonNull private final Integer exponentBase;

/** The Jitter percent on the calculated duration. If not set, a default value will be used. */
private final Integer jitterPercent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,7 @@ public abstract class BaseClientConfiguration {
* within the specified AZ if exits.
*/
private final String clientAZ;

/** Strategy used to determine how and when to reconnect, in case of connection failures. */
private final BackoffStrategy reconnectStrategy;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
@SuperBuilder
@ToString
public class GlideClientConfiguration extends BaseClientConfiguration {
/** Strategy used to determine how and when to reconnect, in case of connection failures. */
private final BackoffStrategy reconnectStrategy;

/** Index of the logical database to connect to. */
private final Integer databaseId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* .requestTimeout(2000)
* .clientName("GLIDE")
* .subscriptionConfiguration(subscriptionConfiguration)
* .reconnectStrategy(reconnectionConfiguration)
* .inflightRequestsLimit(1000)
* .advancedConfiguration(AdvancedGlideClusterClientConfiguration.builder().connectionTimeout(500).build())
* .build();
Expand Down
21 changes: 13 additions & 8 deletions java/client/src/main/java/glide/managers/ConnectionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ private ConnectionRequest.Builder setupConnectionRequestBuilderBaseConfiguration
connectionRequestBuilder.setProtocolValue(configuration.getProtocol().ordinal());
}

if (configuration.getReconnectStrategy() != null) {
var reconnectionStrategyBuilder =
ConnectionRequestOuterClass.ConnectionRetryStrategy.newBuilder()
.setNumberOfRetries(configuration.getReconnectStrategy().getNumOfRetries())
.setExponentBase(configuration.getReconnectStrategy().getExponentBase())
.setFactor(configuration.getReconnectStrategy().getFactor());
if (configuration.getReconnectStrategy().getJitterPercent() != null) {
reconnectionStrategyBuilder.setJitterPercent(
configuration.getReconnectStrategy().getJitterPercent());
}
connectionRequestBuilder.setConnectionRetryStrategy(reconnectionStrategyBuilder.build());
}

return connectionRequestBuilder;
}

Expand All @@ -158,14 +171,6 @@ private ConnectionRequest.Builder setupConnectionRequestBuilderGlideClient(
ConnectionRequest.Builder connectionRequestBuilder =
setupConnectionRequestBuilderBaseConfiguration(configuration);
connectionRequestBuilder.setClusterModeEnabled(false);
if (configuration.getReconnectStrategy() != null) {
connectionRequestBuilder.setConnectionRetryStrategy(
ConnectionRequestOuterClass.ConnectionRetryStrategy.newBuilder()
.setNumberOfRetries(configuration.getReconnectStrategy().getNumOfRetries())
.setFactor(configuration.getReconnectStrategy().getFactor())
.setExponentBase(configuration.getReconnectStrategy().getExponentBase())
.build());
}

if (configuration.getDatabaseId() != null) {
connectionRequestBuilder.setDatabaseId(configuration.getDatabaseId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,96 @@ public void test_az_affinity_replicas_and_primary_without_client_az_throws_Confi
ReadFrom.AZ_AFFINITY_REPLICAS_AND_PRIMARY);
}

@SneakyThrows
@Test
public void test_reconnect_strategy_to_protobuf() {
// setup
GlideClientConfiguration glideClientConfiguration =
GlideClientConfiguration.builder()
.address(NodeAddress.builder().host(HOST).port(PORT).build())
.useTLS(true)
.reconnectStrategy(
BackoffStrategy.builder()
.numOfRetries(10)
.exponentBase(4)
.factor(16)
.jitterPercent(30)
.build())
.build();
ConnectionRequest expectedProtobufConnectionRequest =
ConnectionRequest.newBuilder()
.addAddresses(
ConnectionRequestOuterClass.NodeAddress.newBuilder()
.setHost(HOST)
.setPort(PORT)
.build())
.setTlsMode(TlsMode.SecureTls)
.setConnectionRetryStrategy(
ConnectionRetryStrategy.newBuilder()
.setNumberOfRetries(10)
.setFactor(16)
.setExponentBase(4)
.setJitterPercent(30)
.build())
.build();
CompletableFuture<Response> completedFuture = new CompletableFuture<>();
Response response = Response.newBuilder().setConstantResponse(ConstantResponse.OK).build();
completedFuture.complete(response);

// execute
when(channel.connect(eq(expectedProtobufConnectionRequest))).thenReturn(completedFuture);
CompletableFuture<Void> result = connectionManager.connectToValkey(glideClientConfiguration);

// verify
assertNull(result.get());
}

@SneakyThrows
@Test
public void test_reconnect_strategy_to_protobuf_cluster_client() {
// setup
GlideClusterClientConfiguration glideClusterClientConfiguration =
GlideClusterClientConfiguration.builder()
.address(NodeAddress.builder().host(HOST).port(PORT).build())
.useTLS(true)
.reconnectStrategy(
BackoffStrategy.builder()
.numOfRetries(10)
.exponentBase(4)
.factor(16)
.jitterPercent(30)
.build())
.build();
ConnectionRequest expectedProtobufConnectionRequest =
ConnectionRequest.newBuilder()
.addAddresses(
ConnectionRequestOuterClass.NodeAddress.newBuilder()
.setHost(HOST)
.setPort(PORT)
.build())
.setTlsMode(TlsMode.SecureTls)
.setClusterModeEnabled(true)
.setConnectionRetryStrategy(
ConnectionRetryStrategy.newBuilder()
.setNumberOfRetries(10)
.setFactor(16)
.setExponentBase(4)
.setJitterPercent(30)
.build())
.build();
CompletableFuture<Response> completedFuture = new CompletableFuture<>();
Response response = Response.newBuilder().setConstantResponse(ConstantResponse.OK).build();
completedFuture.complete(response);

// execute
when(channel.connect(eq(expectedProtobufConnectionRequest))).thenReturn(completedFuture);
CompletableFuture<Void> result =
connectionManager.connectToValkey(glideClusterClientConfiguration);

// verify
assertNull(result.get());
}

private void testAzAffinityWithoutClientAzThrowsConfigurationError(ReadFrom readFrom) {
// setup
String az = "us-east-1a";
Expand Down
Loading