Skip to content

Commit 02496af

Browse files
Kaustubh22327rohitesh-wingify
authored andcommitted
feat: Network retry configuration and thread pool
1 parent 3e1c868 commit 02496af

18 files changed

Lines changed: 912 additions & 252 deletions

CHANGELOG.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,48 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.18.0] - 2026-02-11
9+
10+
### Added
11+
12+
- Added network retry mechanism with exponential backoff for failed network requests
13+
- Configurable max retries (default: 3)
14+
- Configurable initial delay (default: 2 seconds)
15+
- Configurable backoff multiplier (default: 2)
16+
- Skips retry for 400 Bad Request errors
17+
- Added bounded thread pool for async network operations
18+
- Configurable max pool size and queue size
19+
- Uses DiscardPolicy for queue overflow handling
20+
- Added debug event support for network retries to VWO
21+
22+
```java
23+
import com.vwo.VWO;
24+
import com.vwo.models.user.VWOInitOptions;
25+
import com.vwo.models.user.RetryConfig;
26+
import java.util.Map;
27+
import java.util.HashMap;
28+
29+
VWOInitOptions vwoInitOptions = new VWOInitOptions();
30+
vwoInitOptions.setSdkKey("sdk-key");
31+
vwoInitOptions.setAccountId(123456);
32+
33+
// Configure Network Retry
34+
RetryConfig retryConfig = new RetryConfig();
35+
retryConfig.setShouldRetry(true); // Enable/Disable retries
36+
retryConfig.setMaxRetries(5); // Max number of retries
37+
retryConfig.setInitialDelay(2); // Initial delay in seconds (default is 2)
38+
retryConfig.setBackoffMultiplier(2); // Backoff multiplier (default is 2)
39+
vwoInitOptions.setRetryConfig(retryConfig);
40+
41+
// Configure Thread Pool for Async Operations
42+
Map<String, Object> threadPoolConfig = new HashMap<>();
43+
threadPoolConfig.put("maxPoolSize", 50); // Max threads for network calls
44+
threadPoolConfig.put("queueSize", 20000); // Max tasks in queue before rejection
45+
vwoInitOptions.setThreadPoolConfig(threadPoolConfig);
46+
47+
VWO instance = VWO.init(vwoInitOptions);
48+
```
49+
850
## [1.17.0] - 2025-01-19
951

1052
### Added
@@ -30,7 +72,7 @@ vwoInitOptions.setProxyUrl("http://custom.proxy.com");
3072
vwoInitOptions.setIsAliasingEnabled(true);
3173
VWO instance = VWO.init(vwoInitOptions);
3274
```
33-
75+
3476
## [1.15.0] - 2025-12-08
3577
### Added
3678

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ limitations under the License. -->
1919

2020
<groupId>com.vwo.sdk</groupId>
2121
<artifactId>vwo-fme-java-sdk</artifactId>
22-
<version>1.17.0</version>
22+
<version>1.18.0</version>
2323
<packaging>jar</packaging>
2424

2525
<name>VWO FME Java SDK</name>

src/main/java/com/vwo/VWOBuilder.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,22 @@ public void setVWOClient(VWOClient vwoClient) {
6464
*/
6565
public VWOBuilder setNetworkManager() {
6666
NetworkManager networkInstance = NetworkManager.getInstance();
67+
68+
// Set logger service first so it can be used for logging during configuration
69+
networkInstance.setLoggerService(loggerService);
70+
71+
// Configure thread pool (always call, uses defaults if no config provided)
72+
networkInstance.configureThreadPool(this.options != null ? this.options.getThreadPoolConfig() : null);
73+
74+
// Attach network client
6775
if (this.options != null && this.options.getNetworkClientInterface() != null) {
6876
networkInstance.attachClient(this.options.getNetworkClientInterface());
6977
} else {
7078
networkInstance.attachClient();
7179
}
80+
81+
// Set retry configuration
82+
networkInstance.setRetryConfig(this.options != null ? this.options.getRetryConfig() : null);
7283
networkInstance.getConfig().setDevelopmentMode(false);
7384
loggerService.log(LogLevelEnum.DEBUG, "SERVICE_INITIALIZED", new HashMap<String, Object>() {
7485
{
@@ -390,16 +401,6 @@ public VWOBuilder initBatching() {
390401
boolean isEventsPerRequestValid = DataTypeUtil.isInteger(eventsPerRequest) && eventsPerRequest > 0 && eventsPerRequest <= Constants.MAX_EVENTS_PER_REQUEST;
391402
boolean isRequestTimeIntervalValid = DataTypeUtil.isInteger(requestTimeInterval) && requestTimeInterval >0;
392403

393-
// Check data type and values for eventsPerRequest and requestTimeInterval
394-
if (!isEventsPerRequestValid && !isRequestTimeIntervalValid) {
395-
loggerService.log(LogLevelEnum.ERROR, "VALUES_MISMATCH_BATCHING_NOT_ENABLED", new HashMap<String, Object>() {
396-
{
397-
put("an", ApiEnum.INIT.getValue());
398-
}
399-
});
400-
return this;
401-
}
402-
403404
// Handle invalid data types for individual parameters
404405
if (!isEventsPerRequestValid) {
405406
loggerService.log(LogLevelEnum.ERROR, "INVALID_EVENTS_PER_REQUEST_VALUE", new HashMap<String, Object>() {

src/main/java/com/vwo/constants/Constants.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@ public class Constants {
2323
public static final int MAX_TRAFFIC_VALUE = 10000;
2424
public static final String STATUS_RUNNING = "RUNNING";
2525

26+
public static final int HTTP_OK = 200;
27+
public static final int HTTP_MULTIPLE_CHOICES = 300;
28+
public static final int HTTP_BAD_REQUEST = 400;
29+
2630
public static final int SEED_VALUE = 1;
2731
public static final int MAX_EVENTS_PER_REQUEST = 5000;
2832
public static final int DEFAULT_REQUEST_TIME_INTERVAL = 600; // 10 * 60(secs) = 600 secs i.e. 10 minutes
2933
public static final int DEFAULT_EVENTS_PER_REQUEST = 100;
3034
public static final String SDK_NAME = "vwo-fme-java-sdk";
31-
public static final String SDK_VERSION = "1.17.0";
35+
public static final String SDK_VERSION = "1.18.0";
3236
public static final long SETTINGS_EXPIRY = 10000000;
3337
public static final long SETTINGS_TIMEOUT = 50000;
3438

@@ -50,4 +54,21 @@ public class Constants {
5054
public static final String NETWORK_CALL_EXCEPTION = "NETWORK_CALL_EXCEPTION";
5155

5256
public static final String IMPACT_ANALYSIS = "IMPACT_ANALYSIS";
57+
58+
// Network retry debug event message types
59+
public static final String NETWORK_CALL_SUCCESS_WITH_RETRIES = "NETWORK_CALL_SUCCESS_WITH_RETRIES";
60+
public static final String NETWORK_CALL_FAILURE_AFTER_MAX_RETRIES = "NETWORK_CALL_FAILURE_AFTER_MAX_RETRIES";
61+
62+
// Retry configuration defaults
63+
public static final boolean DEFAULT_SHOULD_RETRY = true;
64+
public static final int DEFAULT_MAX_RETRIES = 3;
65+
public static final int DEFAULT_INITIAL_DELAY = 2;
66+
public static final int DEFAULT_BACKOFF_MULTIPLIER = 2;
67+
public static final int MIN_BACKOFF_MULTIPLIER = 2;
68+
69+
// Thread pool configuration defaults
70+
public static final int THREAD_POOL_MIN_SIZE = 4; // Minimum threads always alive
71+
public static final int THREAD_POOL_MAX_SIZE = 20; // Maximum threads under load (configurable)
72+
public static final int THREAD_POOL_QUEUE_SIZE = 10000; // Tasks waiting in queue (configurable)
73+
public static final long THREAD_POOL_KEEP_ALIVE_SECONDS = 60L; // Idle thread timeout
5374
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Copyright 2024-2025 Wingify Software Pvt. Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.vwo.models.user;
17+
18+
import com.vwo.constants.Constants;
19+
20+
/**
21+
* Retry configuration class.
22+
* Used to configure network retry behavior with exponential backoff.
23+
*/
24+
public class RetryConfig {
25+
private Boolean shouldRetry;
26+
private Integer maxRetries;
27+
private Integer initialDelay;
28+
private Integer backoffMultiplier;
29+
30+
public RetryConfig() {
31+
this.shouldRetry = Constants.DEFAULT_SHOULD_RETRY;
32+
this.maxRetries = Constants.DEFAULT_MAX_RETRIES;
33+
this.initialDelay = Constants.DEFAULT_INITIAL_DELAY;
34+
this.backoffMultiplier = Constants.DEFAULT_BACKOFF_MULTIPLIER;
35+
}
36+
37+
public RetryConfig(Boolean shouldRetry, Integer maxRetries, Integer initialDelay, Integer backoffMultiplier) {
38+
this.shouldRetry = shouldRetry;
39+
this.maxRetries = maxRetries;
40+
this.initialDelay = initialDelay;
41+
this.backoffMultiplier = backoffMultiplier;
42+
}
43+
44+
// Copy constructor
45+
public RetryConfig(RetryConfig other) {
46+
this.shouldRetry = other.shouldRetry;
47+
this.maxRetries = other.maxRetries;
48+
this.initialDelay = other.initialDelay;
49+
this.backoffMultiplier = other.backoffMultiplier;
50+
}
51+
52+
public Boolean getShouldRetry() {
53+
return shouldRetry;
54+
}
55+
56+
public void setShouldRetry(Boolean shouldRetry) {
57+
this.shouldRetry = shouldRetry;
58+
}
59+
60+
public Integer getMaxRetries() {
61+
return maxRetries;
62+
}
63+
64+
public void setMaxRetries(Integer maxRetries) {
65+
this.maxRetries = maxRetries;
66+
}
67+
68+
public Integer getInitialDelay() {
69+
return initialDelay;
70+
}
71+
72+
public void setInitialDelay(Integer initialDelay) {
73+
this.initialDelay = initialDelay;
74+
}
75+
76+
public Integer getBackoffMultiplier() {
77+
return backoffMultiplier;
78+
}
79+
80+
public void setBackoffMultiplier(Integer backoffMultiplier) {
81+
this.backoffMultiplier = backoffMultiplier;
82+
}
83+
@Override
84+
public String toString() {
85+
return "RetryConfig{" +
86+
"shouldRetry=" + shouldRetry +
87+
", maxRetries=" + maxRetries +
88+
", initialDelay=" + initialDelay +
89+
", backoffMultiplier=" + backoffMultiplier +
90+
'}';
91+
}
92+
}

src/main/java/com/vwo/models/user/VWOInitOptions.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class VWOInitOptions {
4343
private Boolean isUsageStatsDisabled = false;
4444
private Map<String, Object> _vwo_meta = new HashMap<>();
4545
private Boolean isAliasingEnabled = false;
46+
private RetryConfig retryConfig;
47+
private Map<String, Object> threadPoolConfig = new HashMap<>();
4648
private String proxyUrl = "";
4749

4850
public Map<String, Object> getVwoMetaData() {
@@ -157,6 +159,40 @@ public void setIsAliasingEnabled(Boolean isAliasingEnabled) {
157159
this.isAliasingEnabled = isAliasingEnabled;
158160
}
159161

162+
/**
163+
* Gets the retry configuration.
164+
* @return The retry configuration.
165+
*/
166+
public RetryConfig getRetryConfig() {
167+
return retryConfig;
168+
}
169+
170+
/**
171+
* Sets the retry configuration.
172+
* @param retryConfig The retry configuration to set.
173+
*/
174+
public void setRetryConfig(RetryConfig retryConfig) {
175+
this.retryConfig = retryConfig;
176+
}
177+
178+
/**
179+
* Gets the thread pool configuration.
180+
* Supported keys: "maxPoolSize" (Integer), "queueSize" (Integer)
181+
* @return The thread pool configuration map.
182+
*/
183+
public Map<String, Object> getThreadPoolConfig() {
184+
return threadPoolConfig;
185+
}
186+
187+
/**
188+
* Sets the thread pool configuration.
189+
* Supported keys: "maxPoolSize" (Integer), "queueSize" (Integer)
190+
* @param threadPoolConfig The thread pool configuration to set.
191+
*/
192+
public void setThreadPoolConfig(Map<String, Object> threadPoolConfig) {
193+
this.threadPoolConfig = threadPoolConfig;
194+
}
195+
160196
public String getProxyUrl() {
161197
return proxyUrl;
162198
}

0 commit comments

Comments
 (0)