Add configuration setting for TTL of HTTP connections to IRestfulClientFactory (#6204)
* Add configuration setting for TTL of HTTP connections to IRestfulClientFactory * Update changelog and pom.xml * Modify changelog --------- Co-authored-by: James Agnew <jamesagnew@gmail.com>
This commit is contained in:
parent
19af077c2a
commit
554bb08d01
|
@ -37,6 +37,12 @@ public interface IRestfulClientFactory {
|
||||||
*/
|
*/
|
||||||
public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 10000;
|
public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 10000;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default value for {@link #getConnectionTimeToLive()}
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_CONNECTION_TTL = 5000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value for {@link #getServerValidationModeEnum()}
|
* Default value for {@link #getServerValidationModeEnum()}
|
||||||
*/
|
*/
|
||||||
|
@ -75,6 +81,17 @@ public interface IRestfulClientFactory {
|
||||||
*/
|
*/
|
||||||
int getConnectTimeout();
|
int getConnectTimeout();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the connection time to live, in milliseconds. This is the amount of time to keep connections alive for reuse.
|
||||||
|
* <p>
|
||||||
|
* The default value for this setting is defined by {@link #DEFAULT_CONNECTION_TTL}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
default int getConnectionTimeToLive() {
|
||||||
|
return DEFAULT_CONNECTION_TTL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the HTTP client instance. This method will not return null.
|
* Returns the HTTP client instance. This method will not return null.
|
||||||
* @param theUrl
|
* @param theUrl
|
||||||
|
@ -179,6 +196,14 @@ public interface IRestfulClientFactory {
|
||||||
*/
|
*/
|
||||||
void setConnectTimeout(int theConnectTimeout);
|
void setConnectTimeout(int theConnectTimeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the connection time to live, in milliseconds. This is the amount of time to keep connections alive for reuse.
|
||||||
|
* <p>
|
||||||
|
* The default value for this setting is defined by {@link #DEFAULT_CONNECTION_TTL}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
default void setConnectionTimeToLive(int theConnectionTimeToLive) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Apache HTTP client instance to be used by any new restful clients created by this factory. If set to
|
* Sets the Apache HTTP client instance to be used by any new restful clients created by this factory. If set to
|
||||||
* <code>null</code>, a new HTTP client with default settings will be created.
|
* <code>null</code>, a new HTTP client with default settings will be created.
|
||||||
|
|
|
@ -106,9 +106,9 @@ public class HapiFhirCliRestfulClientFactory extends RestfulClientFactory {
|
||||||
.register("https", sslConnectionSocketFactory)
|
.register("https", sslConnectionSocketFactory)
|
||||||
.build();
|
.build();
|
||||||
connectionManager =
|
connectionManager =
|
||||||
new PoolingHttpClientConnectionManager(registry, null, null, null, 5000, TimeUnit.MILLISECONDS);
|
new PoolingHttpClientConnectionManager(registry, null, null, null, getConnectionTimeToLive(), TimeUnit.MILLISECONDS);
|
||||||
} else {
|
} else {
|
||||||
connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
connectionManager = new PoolingHttpClientConnectionManager(getConnectionTimeToLive(), TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionManager.setMaxTotal(getPoolMaxTotal());
|
connectionManager.setMaxTotal(getPoolMaxTotal());
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.cli;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||||
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
|
@ -10,6 +11,7 @@ import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
@ -79,4 +81,13 @@ public class ApacheRestfulClientFactoryTest extends BaseFhirVersionParameterized
|
||||||
assertEquals(SSLHandshakeException.class, e.getCause().getCause().getClass());
|
assertEquals(SSLHandshakeException.class, e.getCause().getCause().getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConnectionTimeToLive() {
|
||||||
|
ApacheRestfulClientFactory clientFactory = new ApacheRestfulClientFactory();
|
||||||
|
|
||||||
|
assertEquals(IRestfulClientFactory.DEFAULT_CONNECTION_TTL, clientFactory.getConnectionTimeToLive());
|
||||||
|
clientFactory.setConnectionTimeToLive(25000);
|
||||||
|
assertEquals(25000, clientFactory.getConnectionTimeToLive());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.cli.client;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||||
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
|
@ -159,4 +160,15 @@ public class HapiFhirCliRestfulClientFactoryTest extends BaseFhirVersionParamete
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("baseParamsProvider")
|
||||||
|
public void testConnectionTimeToLive(FhirVersionEnum theFhirVersion) {
|
||||||
|
FhirVersionParams fhirVersionParams = getFhirVersionParams(theFhirVersion);
|
||||||
|
HapiFhirCliRestfulClientFactory clientFactory = new HapiFhirCliRestfulClientFactory(fhirVersionParams.getFhirContext());
|
||||||
|
|
||||||
|
assertEquals(IRestfulClientFactory.DEFAULT_CONNECTION_TTL, clientFactory.getConnectionTimeToLive());
|
||||||
|
clientFactory.setConnectionTimeToLive(25000);
|
||||||
|
assertEquals(25000, clientFactory.getConnectionTimeToLive());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.rest.client.api.Header;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||||
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
import ca.uhn.fhir.rest.client.impl.RestfulClientFactory;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
|
import okhttp3.ConnectionPool;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
@ -65,6 +66,7 @@ public class OkHttpRestfulClientFactory extends RestfulClientFactory {
|
||||||
myNativeClient = new OkHttpClient()
|
myNativeClient = new OkHttpClient()
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.connectTimeout(getConnectTimeout(), TimeUnit.MILLISECONDS)
|
.connectTimeout(getConnectTimeout(), TimeUnit.MILLISECONDS)
|
||||||
|
.connectionPool(new ConnectionPool(5, getConnectionTimeToLive(), TimeUnit.MILLISECONDS))
|
||||||
.readTimeout(getSocketTimeout(), TimeUnit.MILLISECONDS)
|
.readTimeout(getSocketTimeout(), TimeUnit.MILLISECONDS)
|
||||||
.writeTimeout(getSocketTimeout(), TimeUnit.MILLISECONDS)
|
.writeTimeout(getSocketTimeout(), TimeUnit.MILLISECONDS)
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.okhttp;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
|
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||||
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
import ca.uhn.fhir.test.BaseFhirVersionParameterizedTest;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
@ -71,6 +72,13 @@ public class OkHttpRestfulClientFactoryTest extends BaseFhirVersionParameterized
|
||||||
assertEquals(1516, ((OkHttpClient) clientFactory.getNativeClient()).connectTimeoutMillis());
|
assertEquals(1516, ((OkHttpClient) clientFactory.getNativeClient()).connectTimeoutMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConnectionTimeToLive() {
|
||||||
|
assertEquals(IRestfulClientFactory.DEFAULT_CONNECTION_TTL, clientFactory.getConnectionTimeToLive());
|
||||||
|
clientFactory.setConnectionTimeToLive(25000);
|
||||||
|
assertEquals(25000, clientFactory.getConnectionTimeToLive());
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("baseParamsProvider")
|
@MethodSource("baseParamsProvider")
|
||||||
public void testNativeClientHttp(FhirVersionEnum theFhirVersion) throws Exception {
|
public void testNativeClientHttp(FhirVersionEnum theFhirVersion) throws Exception {
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class ApacheRestfulClientFactory extends RestfulClientFactory {
|
||||||
.disableCookieManagement();
|
.disableCookieManagement();
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager =
|
PoolingHttpClientConnectionManager connectionManager =
|
||||||
new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
new PoolingHttpClientConnectionManager(getConnectionTimeToLive(), TimeUnit.MILLISECONDS);
|
||||||
connectionManager.setMaxTotal(getPoolMaxTotal());
|
connectionManager.setMaxTotal(getPoolMaxTotal());
|
||||||
connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute());
|
connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute());
|
||||||
builder.setConnectionManager(connectionManager);
|
builder.setConnectionManager(connectionManager);
|
||||||
|
|
|
@ -57,6 +57,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
||||||
private final Set<String> myValidatedServerBaseUrls = Collections.synchronizedSet(new HashSet<>());
|
private final Set<String> myValidatedServerBaseUrls = Collections.synchronizedSet(new HashSet<>());
|
||||||
private int myConnectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
|
private int myConnectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
|
||||||
private int myConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
private int myConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||||
|
private int myConnectionTimeToLive = DEFAULT_CONNECTION_TTL;
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private final Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers =
|
private final Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers =
|
||||||
new HashMap<>();
|
new HashMap<>();
|
||||||
|
@ -91,6 +92,11 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
||||||
return myConnectTimeout;
|
return myConnectTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized int getConnectionTimeToLive() {
|
||||||
|
return myConnectionTimeToLive;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the proxy username to authenticate with the HTTP proxy
|
* Return the proxy username to authenticate with the HTTP proxy
|
||||||
*/
|
*/
|
||||||
|
@ -210,6 +216,12 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
||||||
resetHttpClient();
|
resetHttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setConnectionTimeToLive(int theConnectionTimeToLive) {
|
||||||
|
myConnectionTimeToLive = theConnectionTimeToLive;
|
||||||
|
resetHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the context associated with this client factory. Must not be called more than once.
|
* Sets the context associated with this client factory. Must not be called more than once.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 6184
|
||||||
|
title: "Added a configuration setting for the TTL of HTTP connections to IRestfulClientFactory.
|
||||||
|
The following implementations have been updated to respect this new setting:
|
||||||
|
1. ApacheRestfulClientFactory
|
||||||
|
2. OkHttpRestfulClientFactory
|
||||||
|
3. HapiFhirCliRestfulClientFactory
|
||||||
|
Thanks to Alex Kopp and Alex Cote for the contribution!
|
||||||
|
"
|
24
pom.xml
24
pom.xml
|
@ -919,15 +919,21 @@
|
||||||
<id>adriennesox</id>
|
<id>adriennesox</id>
|
||||||
<name>Adrienne Sox</name>
|
<name>Adrienne Sox</name>
|
||||||
<organization>Galileo, Inc.</organization>
|
<organization>Galileo, Inc.</organization>
|
||||||
</developer>
|
</developer>
|
||||||
<developer>
|
<developer>
|
||||||
<id>melihaydogd</id>
|
<id>melihaydogd</id>
|
||||||
<name>Ahmet Melih Aydoğdu</name>
|
<name>Ahmet Melih Aydoğdu</name>
|
||||||
</developer>
|
</developer>
|
||||||
<developer>
|
<developer>
|
||||||
<id>alexrkopp</id>
|
<id>alexrkopp</id>
|
||||||
<name>Alex Kopp</name>
|
<name>Alex Kopp</name>
|
||||||
</developer>
|
<organization>athenahealth</organization>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>acoteathn</id>
|
||||||
|
<name>Alex Cote</name>
|
||||||
|
<organization>athenahealth</organization>
|
||||||
|
</developer>
|
||||||
</developers>
|
</developers>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
|
|
Loading…
Reference in New Issue