Skip to content

Commit 38a359d

Browse files
authored
[Csl-985] java sdk add support for http configs (#77)
* Expose http client getters and setters * Add config object and function * Adjust timeout * Add tests for set client and config client * Rename functions * Add null tests for config * Typo * Use class instead of instance * Test name change * Address comments, change test name and defaults.
1 parent 813bb8c commit 38a359d

File tree

4 files changed

+270
-8
lines changed

4 files changed

+270
-8
lines changed

constructorio-client/src/main/java/io/constructor/client/ConstructorIO.java

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
import okhttp3.Request.Builder;
3535
import okhttp3.RequestBody;
3636
import okhttp3.Response;
37+
import okhttp3.Interceptor;
38+
import okhttp3.Dispatcher;
39+
import okhttp3.ConnectionPool;
3740

3841
/**
3942
* Constructor.io Client
@@ -53,22 +56,58 @@ public class ConstructorIO {
5356
/**
5457
* the HTTP client used by all instances (with retry, only for idempotent requests like GET)
5558
*/
56-
private static OkHttpClient clientWithRetry = new OkHttpClient.Builder()
57-
.addInterceptor(new ConstructorInterceptor())
59+
private static OkHttpClient clientWithRetry = client.newBuilder()
5860
.retryOnConnectionFailure(true)
5961
.build();
6062

6163
/**
62-
* @param newClient the HTTP client to use by all instances
64+
* @param newClient the OkHttpClient to use by all instances
6365
*/
64-
protected static void setClient(OkHttpClient newClient) {
65-
client = newClient;
66+
public static void setHttpClient(OkHttpClient newClient) {
67+
OkHttpClient.Builder builder = newClient.newBuilder().retryOnConnectionFailure(false);
68+
List<Interceptor> interceptors = newClient.interceptors();
69+
Boolean exists = false;
70+
71+
for (Interceptor interceptor : interceptors) {
72+
if (interceptor instanceof ConstructorInterceptor) {
73+
exists = true;
74+
break;
75+
}
76+
}
77+
if (!exists) {
78+
builder.addInterceptor(new ConstructorInterceptor());
79+
}
80+
81+
client = builder.build();
82+
clientWithRetry = builder.retryOnConnectionFailure(true).build();
6683
}
6784

85+
/**
86+
*
87+
* @param config the Http client config
88+
*/
89+
public static void setHttpClientConfig(HttpClientConfig config) {
90+
OkHttpClient.Builder builder = client.newBuilder();
91+
Dispatcher dispatcher = new Dispatcher();
92+
93+
builder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
94+
builder.writeTimeout(config.getWriteTimeout(), TimeUnit.MILLISECONDS);
95+
builder.connectTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS);
96+
97+
ConnectionPool pool = new ConnectionPool(config.getConnectionPoolMaxIdleConnections(), config.getConnectionPoolKeepAliveDuration(), TimeUnit.MILLISECONDS);
98+
builder.connectionPool(pool);
99+
100+
dispatcher.setMaxRequests(config.getDispatcherMaxRequests());
101+
dispatcher.setMaxRequestsPerHost(config.getDispatcherMaxRequestsPerHost());
102+
builder.dispatcher(dispatcher);
103+
104+
client = builder.build();
105+
clientWithRetry = builder.retryOnConnectionFailure(true).build();
106+
}
68107
/**
69108
* @return the HTTP client used by all instances
70109
*/
71-
protected static OkHttpClient getClient() {
110+
public static OkHttpClient getHttpClient() {
72111
return client;
73112
}
74113

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package io.constructor.client;
2+
3+
public class HttpClientConfig {
4+
private int readTimeout;
5+
private int writeTimeout;
6+
private int connectTimeout;
7+
private int connectionPoolMaxIdleConnections;
8+
private int connectionPoolKeepAliveDuration;
9+
private int dispatcherMaxRequests;
10+
private int dispatcherMaxRequestsPerHost;
11+
12+
HttpClientConfig() {
13+
this.readTimeout = 30000;
14+
this.writeTimeout = 30000;
15+
this.connectTimeout = 10000;
16+
this.connectionPoolMaxIdleConnections = 5;
17+
this.connectionPoolKeepAliveDuration = 300000;
18+
this.dispatcherMaxRequests = 64;
19+
this.dispatcherMaxRequestsPerHost = 5;
20+
}
21+
22+
/**
23+
* @return the read timeout in milliseconds
24+
*/
25+
public int getReadTimeout() {
26+
return readTimeout;
27+
}
28+
29+
/**
30+
* @param readTimeout the read timeout for new connections in milliseconds
31+
*/
32+
public void setReadTimeout(int readTimeout) {
33+
this.readTimeout = readTimeout;
34+
}
35+
36+
/**
37+
* @return the write timeout in milliseconds
38+
*/
39+
public int getWriteTimeout() {
40+
return writeTimeout;
41+
}
42+
43+
/**
44+
* @param writeTimeout the write timeout for new connections in milliseconds
45+
*/
46+
public void setWriteTimeout(int writeTimeout) {
47+
this.writeTimeout = writeTimeout;
48+
}
49+
50+
/**
51+
* @return the connect timeout in milliseconds
52+
*/
53+
public int getConnectTimeout() {
54+
return connectTimeout;
55+
}
56+
57+
/**
58+
* @param connectTimeout the connect timeout for new connections in milliseconds
59+
*/
60+
public void setConnectTimeout(int connectTimeout) {
61+
this.connectTimeout = connectTimeout;
62+
}
63+
64+
/**
65+
* @return the maximum number of idle connections in the pool
66+
*/
67+
public int getConnectionPoolMaxIdleConnections() {
68+
return connectionPoolMaxIdleConnections;
69+
}
70+
71+
/**
72+
* @param connectionPoolMaxIdleConnections the maximum number of idle connections in the pool
73+
*/
74+
public void setConnectionPoolMaxIdleConnections(int connectionPoolMaxIdleConnections) {
75+
this.connectionPoolMaxIdleConnections = connectionPoolMaxIdleConnections;
76+
}
77+
78+
/**
79+
* @return the keep alive duration in milliseconds
80+
*/
81+
public int getConnectionPoolKeepAliveDuration() {
82+
return connectionPoolKeepAliveDuration;
83+
}
84+
85+
/**
86+
* @param connectionPoolKeepAliveDuration the time in milliseconds to keep the connection alive in the pool before closing it
87+
*/
88+
public void setConnectionPoolKeepAliveDuration(int connectionPoolKeepAliveDuration) {
89+
this.connectionPoolKeepAliveDuration = connectionPoolKeepAliveDuration;
90+
}
91+
92+
/**
93+
* @return the max requests to execute concurrently
94+
*/
95+
public int getDispatcherMaxRequests() {
96+
return dispatcherMaxRequests;
97+
}
98+
99+
/**
100+
* @param dispatcherMaxRequests the max requests to execute concurrently
101+
*/
102+
public void setDispatcherMaxRequests(int dispatcherMaxRequests) {
103+
this.dispatcherMaxRequests = dispatcherMaxRequests;
104+
}
105+
106+
/**
107+
* @return the max requests for each host to execute concurrently
108+
*/
109+
public int getDispatcherMaxRequestsPerHost() {
110+
return dispatcherMaxRequestsPerHost;
111+
}
112+
113+
/**
114+
* @param dispatcherMaxRequestsPerHost the max requests for each host to execute concurrently
115+
*/
116+
public void setDispatcherMaxRequestsPerHost(int dispatcherMaxRequestsPerHost) {
117+
this.dispatcherMaxRequestsPerHost = dispatcherMaxRequestsPerHost;
118+
}
119+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package io.constructor.client;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNull;
5+
6+
import java.util.concurrent.TimeUnit;
7+
8+
import okhttp3.Dispatcher;
9+
import okhttp3.OkHttpClient;
10+
import org.junit.After;
11+
import org.junit.Rule;
12+
import org.junit.Test;
13+
import org.junit.rules.ExpectedException;
14+
15+
public class ConstructorIOHttpClientConfigTest {
16+
private String token = System.getenv("TEST_API_TOKEN");
17+
private String apiKey = System.getenv("TEST_API_KEY");
18+
19+
@Rule
20+
public ExpectedException thrown = ExpectedException.none();
21+
22+
@After
23+
public void resetClient() {
24+
ConstructorIO.setHttpClient(new OkHttpClient.Builder()
25+
.addInterceptor(new ConstructorInterceptor())
26+
.retryOnConnectionFailure(false)
27+
.readTimeout(30, TimeUnit.SECONDS)
28+
.writeTimeout(30, TimeUnit.SECONDS)
29+
.build());
30+
}
31+
32+
@Test
33+
public void setHttpClientShouldSetClientProperly() {
34+
assertEquals(30000, ConstructorIO.getHttpClient().readTimeoutMillis());
35+
assertEquals(30000, ConstructorIO.getHttpClient().writeTimeoutMillis());
36+
assertEquals(10000, ConstructorIO.getHttpClient().connectTimeoutMillis());
37+
assertEquals(64, ConstructorIO.getHttpClient().dispatcher().getMaxRequests());
38+
assertEquals(5, ConstructorIO.getHttpClient().dispatcher().getMaxRequestsPerHost());
39+
40+
Dispatcher dispatcher = new Dispatcher();
41+
dispatcher.setMaxRequestsPerHost(2);
42+
dispatcher.setMaxRequests(20);
43+
ConstructorIO.setHttpClient(ConstructorIO.getHttpClient().newBuilder()
44+
.readTimeout(5, TimeUnit.SECONDS)
45+
.writeTimeout(5, TimeUnit.SECONDS)
46+
.connectTimeout(5, TimeUnit.SECONDS)
47+
.dispatcher(dispatcher).build());
48+
49+
assertEquals(5000, ConstructorIO.getHttpClient().readTimeoutMillis());
50+
assertEquals(5000, ConstructorIO.getHttpClient().writeTimeoutMillis());
51+
assertEquals(5000, ConstructorIO.getHttpClient().connectTimeoutMillis());
52+
assertEquals(20, ConstructorIO.getHttpClient().dispatcher().getMaxRequests());
53+
assertEquals(2, ConstructorIO.getHttpClient().dispatcher().getMaxRequestsPerHost());
54+
assertEquals(1, ConstructorIO.getHttpClient().interceptors().size());
55+
}
56+
57+
@Test
58+
public void setHttpClientConfigShouldConfigClientProperly() {
59+
assertEquals(30000, ConstructorIO.getHttpClient().readTimeoutMillis());
60+
assertEquals(30000, ConstructorIO.getHttpClient().writeTimeoutMillis());
61+
assertEquals(10000, ConstructorIO.getHttpClient().connectTimeoutMillis());
62+
assertEquals(64, ConstructorIO.getHttpClient().dispatcher().getMaxRequests());
63+
assertEquals(5, ConstructorIO.getHttpClient().dispatcher().getMaxRequestsPerHost());
64+
65+
HttpClientConfig config = new HttpClientConfig();
66+
config.setConnectTimeout(500);
67+
config.setDispatcherMaxRequests(30);
68+
config.setDispatcherMaxRequestsPerHost(20);
69+
config.setReadTimeout(100);
70+
config.setWriteTimeout(100);
71+
ConstructorIO.setHttpClientConfig(config);
72+
73+
assertEquals(100, ConstructorIO.getHttpClient().readTimeoutMillis());
74+
assertEquals(100, ConstructorIO.getHttpClient().writeTimeoutMillis());
75+
assertEquals(500, ConstructorIO.getHttpClient().connectTimeoutMillis());
76+
assertEquals(30, ConstructorIO.getHttpClient().dispatcher().getMaxRequests());
77+
assertEquals(20, ConstructorIO.getHttpClient().dispatcher().getMaxRequestsPerHost());
78+
}
79+
80+
@Test
81+
public void setHttpClientConfigWithEmptyConfigShouldReturnDefaults() {
82+
assertEquals(30000, ConstructorIO.getHttpClient().readTimeoutMillis());
83+
assertEquals(30000, ConstructorIO.getHttpClient().writeTimeoutMillis());
84+
assertEquals(10000, ConstructorIO.getHttpClient().connectTimeoutMillis());
85+
assertEquals(64, ConstructorIO.getHttpClient().dispatcher().getMaxRequests());
86+
assertEquals(5, ConstructorIO.getHttpClient().dispatcher().getMaxRequestsPerHost());
87+
88+
HttpClientConfig config = new HttpClientConfig();
89+
assertEquals(64, config.getDispatcherMaxRequests());
90+
assertEquals(5, config.getDispatcherMaxRequestsPerHost());
91+
assertEquals(30000, config.getReadTimeout());
92+
assertEquals(30000, config.getWriteTimeout());
93+
assertEquals(10000, config.getConnectTimeout());
94+
assertEquals(300000, config.getConnectionPoolKeepAliveDuration());
95+
assertEquals(5, config.getConnectionPoolMaxIdleConnections());
96+
ConstructorIO.setHttpClientConfig(config);
97+
98+
assertEquals(30000, ConstructorIO.getHttpClient().readTimeoutMillis());
99+
assertEquals(30000, ConstructorIO.getHttpClient().writeTimeoutMillis());
100+
assertEquals(10000, ConstructorIO.getHttpClient().connectTimeoutMillis());
101+
assertEquals(64, ConstructorIO.getHttpClient().dispatcher().getMaxRequests());
102+
assertEquals(5, ConstructorIO.getHttpClient().dispatcher().getMaxRequestsPerHost());
103+
}
104+
}

constructorio-client/src/test/java/io/constructor/client/Utils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public static String getTestResource(String filename) throws Exception {
6868
public static void enableHTTPLogging() {
6969
HttpLoggingInterceptor logger = new HttpLoggingInterceptor();
7070
logger.setLevel(Level.NONE);
71-
OkHttpClient client = ConstructorIO.getClient();
71+
OkHttpClient client = ConstructorIO.getHttpClient();
7272
OkHttpClient newClient = client.newBuilder().addInterceptor(logger).build();
73-
ConstructorIO.setClient(newClient);
73+
ConstructorIO.setHttpClient(newClient);
7474
}
7575
}

0 commit comments

Comments
 (0)