Merge branch 'stable-3.3' into stable-3.4
* stable-3.3:
Honour {httpd,sshd}.gracefulStopTimeout in gerrit.sh
Elasticsearch: Discontinue EOL version 7.5 support
Change-Id: I44a4bf79a2a7a3854d7fc0cc7c9261a5ab621aa4
diff --git a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index e56f470..44a377a 100644
--- a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -84,6 +84,9 @@
protected static final String BULK = "_bulk";
protected static final String MAPPINGS = "mappings";
protected static final String ORDER = "order";
+ protected static final String DESC_SORT_ORDER = "desc";
+ protected static final String ASC_SORT_ORDER = "asc";
+ protected static final String UNMAPPED_TYPE = "unmapped_type";
protected static final String SEARCH = "_search";
protected static final String SETTINGS = "settings";
@@ -288,7 +291,7 @@
protected JsonArray getSortArray(String idFieldName) {
JsonObject properties = new JsonObject();
- properties.addProperty(ORDER, "asc");
+ properties.addProperty(ORDER, ASC_SORT_ORDER);
JsonArray sortArray = new JsonArray();
addNamedElement(idFieldName, properties, sortArray);
diff --git a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
index 625a598..162654d 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
@@ -37,6 +37,7 @@
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.Predicate;
@@ -57,6 +58,9 @@
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
@@ -133,14 +137,24 @@
private JsonArray getSortArray() {
JsonObject properties = new JsonObject();
- properties.addProperty(ORDER, "desc");
+ properties.addProperty(ORDER, DESC_SORT_ORDER);
JsonArray sortArray = new JsonArray();
addNamedElement(ChangeField.UPDATED.getName(), properties, sortArray);
+ addNamedElement(ChangeField.MERGED_ON.getName(), getMergedOnSortOptions(), sortArray);
addNamedElement(idField.getName(), properties, sortArray);
return sortArray;
}
+ private JsonObject getMergedOnSortOptions() {
+ JsonObject sortOptions = new JsonObject();
+ sortOptions.addProperty(ORDER, DESC_SORT_ORDER);
+ // Ignore the sort field if it does not exist in index. Otherwise the search would fail on open
+ // changes, because the corresponding documents do not have mergedOn field.
+ sortOptions.addProperty(UNMAPPED_TYPE, ElasticMapping.TIMESTAMP_FIELD_TYPE);
+ return sortOptions;
+ }
+
@Override
protected String getDeleteActions(Change.Id c) {
return getDeleteRequest(c);
@@ -341,7 +355,7 @@
// Ref-state.
if (fields.contains(ChangeField.REF_STATE.getName())) {
- cd.setRefStates(getByteArray(source, ChangeField.REF_STATE.getName()));
+ cd.setRefStates(RefState.parseStates(getByteArray(source, ChangeField.REF_STATE.getName())));
}
// Ref-state-pattern.
@@ -361,6 +375,10 @@
cd);
}
+ if (fields.contains(ChangeField.MERGED_ON.getName())) {
+ decodeMergedOn(source, cd);
+ }
+
return cd;
}
@@ -396,4 +414,18 @@
}
out.setUnresolvedCommentCount(count.getAsInt());
}
+
+ private void decodeMergedOn(JsonObject doc, ChangeData out) {
+ JsonElement mergedOnField = doc.get(ChangeField.MERGED_ON.getName());
+
+ Timestamp mergedOn = null;
+ if (mergedOnField != null) {
+ // Parse from ElasticMapping.TIMESTAMP_FIELD_FORMAT.
+ // We currently use built-in ISO-based dateOptionalTime.
+ // https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats
+ DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_INSTANT;
+ mergedOn = Timestamp.from(Instant.from(isoFormatter.parse(mergedOnField.getAsString())));
+ }
+ out.setMergedOn(mergedOn);
+ }
}
diff --git a/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java b/java/com/google/gerrit/elasticsearch/ElasticConfiguration.java
index 06b128c..c443529 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/ElasticGroupIndex.java b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
index f8c2ec5..781ed43 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
@@ -20,6 +20,7 @@
import com.google.gerrit.elasticsearch.bulk.IndexRequest;
import com.google.gerrit.elasticsearch.bulk.UpdateRequest;
import com.google.gerrit.entities.AccountGroup;
+import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.Schema;
@@ -28,7 +29,6 @@
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.index.IndexUtils;
import com.google.gerrit.server.index.group.GroupField;
import com.google.gerrit.server.index.group.GroupIndex;
diff --git a/java/com/google/gerrit/elasticsearch/ElasticMapping.java b/java/com/google/gerrit/elasticsearch/ElasticMapping.java
index f8c4168..edd05c9 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticMapping.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticMapping.java
@@ -21,6 +21,10 @@
import java.util.Map;
class ElasticMapping {
+
+ protected static final String TIMESTAMP_FIELD_TYPE = "date";
+ protected static final String TIMESTAMP_FIELD_FORMAT = "dateOptionalTime";
+
static MappingProperties createMapping(Schema<?> schema, ElasticQueryAdapter adapter) {
ElasticMapping.Builder mapping = new ElasticMapping.Builder(adapter);
for (FieldDef<?, ?> field : schema.getFields().values()) {
@@ -71,9 +75,9 @@
}
Builder addTimestamp(String name) {
- FieldProperties properties = new FieldProperties("date");
- properties.type = "date";
- properties.format = "dateOptionalTime";
+ FieldProperties properties = new FieldProperties(TIMESTAMP_FIELD_TYPE);
+ properties.type = TIMESTAMP_FIELD_TYPE;
+ properties.format = TIMESTAMP_FIELD_FORMAT;
fields.put(name, properties);
return this;
}
diff --git a/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java b/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
index d05e91c..40ac603 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticQueryBuilder.java
@@ -29,7 +29,6 @@
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.RegexPredicate;
import com.google.gerrit.index.query.TimestampRangePredicate;
-import com.google.gerrit.server.query.change.AfterPredicate;
import java.time.Instant;
public class ElasticQueryBuilder {
@@ -130,7 +129,9 @@
private <T> QueryBuilder timestampQuery(IndexPredicate<T> p) throws QueryParseException {
if (p instanceof TimestampRangePredicate) {
TimestampRangePredicate<T> r = (TimestampRangePredicate<T>) p;
- if (p instanceof AfterPredicate) {
+ if (r.getMaxTimestamp().getTime() == Long.MAX_VALUE) {
+ // The time range only has the start value, search from the start to the max supported value
+ // Long.MAX_VALUE
return QueryBuilders.rangeQuery(r.getField().getName())
.gte(Instant.ofEpochMilli(r.getMinTimestamp().getTime()));
}
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;
diff --git a/javatests/com/google/gerrit/elasticsearch/BUILD b/javatests/com/google/gerrit/elasticsearch/BUILD
index be35d5a..3036811 100644
--- a/javatests/com/google/gerrit/elasticsearch/BUILD
+++ b/javatests/com/google/gerrit/elasticsearch/BUILD
@@ -55,7 +55,6 @@
ELASTICSEARCH_TAGS = [
"docker",
"elastic",
- "exclusive",
]
[junit_tests(