Elasticsearch: Add support for configuring REST client timeouts
Specifically, allow for configuring the initial connect timeout and the
general socket timeout.
Trying to migrate an existing gerrit instance from LUCENE to
ElasticSearch resulted in the re-index failing due to socket timeouts.
Change-Id: Icd42c26c2671a3b4bf64abe5f59951f65c6339b4
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 811f7b7..7ab97e65 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3323,6 +3323,19 @@
+
Defaults to 10000.
+[[elasticsearch.connectTimeout]]elasticsearch.connectTimeout::
++
+Sets the timeout for connecting to elasticsearch.
++
+Defaults to `1 second`.
+
+[[elasticsearch.socketTimeout]]elasticsearch.socketTimeout::
++
+Sets the timeout for the underlying connection. For more information, refer to
+link:#httpd.idleTimeout[`httpd.idleTimeout`].
++
+Defaults to `30 seconds`.
+
==== Elasticsearch Security
When security is enabled in Elasticsearch, the username and password must be provided.
diff --git a/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java b/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
index 06b128c..c4435297 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
@@ -26,8 +26,10 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import org.apache.http.HttpHost;
import org.eclipse.jgit.lib.Config;
+import org.elasticsearch.client.RestClientBuilder;
@Singleton
class ElasticConfiguration {
@@ -41,12 +43,16 @@
static final String KEY_NUMBER_OF_SHARDS = "numberOfShards";
static final String KEY_NUMBER_OF_REPLICAS = "numberOfReplicas";
static final String KEY_MAX_RESULT_WINDOW = "maxResultWindow";
+ static final String KEY_CONNECT_TIMEOUT = "connectTimeout";
+ static final String KEY_SOCKET_TIMEOUT = "socketTimeout";
static final String DEFAULT_PORT = "9200";
static final String DEFAULT_USERNAME = "elastic";
static final int DEFAULT_NUMBER_OF_SHARDS = 1;
static final int DEFAULT_NUMBER_OF_REPLICAS = 1;
static final int DEFAULT_MAX_RESULT_WINDOW = 10000;
+ static final int DEFAULT_CONNECT_TIMEOUT = RestClientBuilder.DEFAULT_CONNECT_TIMEOUT_MILLIS;
+ static final int DEFAULT_SOCKET_TIMEOUT = RestClientBuilder.DEFAULT_SOCKET_TIMEOUT_MILLIS;
private final Config cfg;
private final List<HttpHost> hosts;
@@ -56,6 +62,8 @@
final int numberOfShards;
final int numberOfReplicas;
final int maxResultWindow;
+ final int connectTimeout;
+ final int socketTimeout;
final String prefix;
@Inject
@@ -74,6 +82,22 @@
cfg.getInt(SECTION_ELASTICSEARCH, null, KEY_NUMBER_OF_REPLICAS, DEFAULT_NUMBER_OF_REPLICAS);
this.maxResultWindow =
cfg.getInt(SECTION_ELASTICSEARCH, null, KEY_MAX_RESULT_WINDOW, DEFAULT_MAX_RESULT_WINDOW);
+ this.connectTimeout =
+ (int)
+ cfg.getTimeUnit(
+ SECTION_ELASTICSEARCH,
+ null,
+ KEY_CONNECT_TIMEOUT,
+ DEFAULT_CONNECT_TIMEOUT,
+ TimeUnit.MILLISECONDS);
+ this.socketTimeout =
+ (int)
+ cfg.getTimeUnit(
+ SECTION_ELASTICSEARCH,
+ null,
+ KEY_SOCKET_TIMEOUT,
+ DEFAULT_SOCKET_TIMEOUT,
+ TimeUnit.MILLISECONDS);
this.hosts = new ArrayList<>();
for (String server : cfg.getStringList(SECTION_ELASTICSEARCH, null, KEY_SERVER)) {
try {
diff --git a/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java b/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
index f635b23..b41f365 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
@@ -27,6 +27,7 @@
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.Request;
@@ -128,10 +129,19 @@
private RestClient build() {
RestClientBuilder builder = RestClient.builder(cfg.getHosts());
+ setConfiguredTimeouts(builder);
setConfiguredCredentialsIfAny(builder);
return builder.build();
}
+ private void setConfiguredTimeouts(RestClientBuilder builder) {
+ builder.setRequestConfigCallback(
+ (RequestConfig.Builder requestConfigBuilder) ->
+ requestConfigBuilder
+ .setConnectTimeout(cfg.connectTimeout)
+ .setSocketTimeout(cfg.socketTimeout));
+ }
+
private void setConfiguredCredentialsIfAny(RestClientBuilder builder) {
String username = cfg.username;
String password = cfg.password;