Skip to content

Commit 76a54c5

Browse files
committed
Merge remote-tracking branch 'upstream/main' into include-default-index-sort
2 parents df81e03 + 2513135 commit 76a54c5

File tree

110 files changed

+1930
-966
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+1930
-966
lines changed

docs/changelog/131485.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 131485
2+
summary: Run single phase aggregation when possible
3+
area: ES|QL
4+
type: enhancement
5+
issues: []

docs/changelog/135776.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 135776
2+
summary: Fix KQL case-sensitivity for keyword fields in ES|QL
3+
area: Search
4+
type: bug
5+
issues:
6+
- 135772

muted-tests.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,24 @@ tests:
594594
- class: org.elasticsearch.datastreams.TSDBIndexingIT
595595
method: testTsdbTemplatesNoKeywordFieldType
596596
issue: https://github.com/elastic/elasticsearch/issues/135746
597+
- class: org.elasticsearch.xpack.esql.expression.function.aggregate.IncreaseTests
598+
method: testGroupingAggregate {TestCase=<small positive doubles>}
599+
issue: https://github.com/elastic/elasticsearch/issues/135752
600+
- class: org.elasticsearch.xpack.esql.expression.function.aggregate.IncreaseTests
601+
method: testGroupingAggregate {TestCase=<positive ints>}
602+
issue: https://github.com/elastic/elasticsearch/issues/135753
603+
- class: org.elasticsearch.xpack.esql.expression.function.aggregate.IncreaseTests
604+
method: testGroupingAggregate {TestCase=<positive longs>}
605+
issue: https://github.com/elastic/elasticsearch/issues/135754
606+
- class: org.elasticsearch.xpack.esql.expression.function.aggregate.IncreaseTests
607+
method: testGroupingAggregate {TestCase=<big positive doubles>}
608+
issue: https://github.com/elastic/elasticsearch/issues/135755
609+
- class: org.elasticsearch.xpack.esql.ccq.AllSupportedFieldsIT
610+
method: testFetchDenseVector {pref=null mode=time_series}
611+
issue: https://github.com/elastic/elasticsearch/issues/135762
612+
- class: org.elasticsearch.xpack.esql.expression.function.aggregate.IrateTests
613+
method: testGroupingAggregate {TestCase=<positive longs>}
614+
issue: https://github.com/elastic/elasticsearch/issues/135775
597615

598616
# Examples:
599617
#
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"inference.put_contextualai": {
3+
"documentation": {
4+
"url": "https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put-contextualai",
5+
"description": "Create an Contextual AI inference endpoint"
6+
},
7+
"stability": "stable",
8+
"visibility": "public",
9+
"headers": {
10+
"accept": [
11+
"application/json"
12+
],
13+
"content_type": [
14+
"application/json"
15+
]
16+
},
17+
"url": {
18+
"paths": [
19+
{
20+
"path": "/_inference/{task_type}/{contextualai_inference_id}",
21+
"methods": [
22+
"PUT"
23+
],
24+
"parts": {
25+
"task_type": {
26+
"type": "string",
27+
"description": "The task type"
28+
},
29+
"contextualai_inference_id": {
30+
"type": "string",
31+
"description": "The inference Id"
32+
}
33+
}
34+
}
35+
]
36+
},
37+
"body": {
38+
"description": "The inference endpoint's task and service settings"
39+
}
40+
}
41+
}

server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,7 +2099,7 @@ public void onResponse(SearchResponse searchResponse) {
20992099
}
21002100
}
21012101
}
2102-
searchResponseMetrics.incrementResponseCount(responseCountTotalStatus);
2102+
searchResponseMetrics.incrementResponseCount(responseCountTotalStatus, searchRequestAttributes);
21032103

21042104
if (collectCCSTelemetry) {
21052105
extractCCSTelemetry(searchResponse);
@@ -2115,7 +2115,7 @@ public void onResponse(SearchResponse searchResponse) {
21152115

21162116
@Override
21172117
public void onFailure(Exception e) {
2118-
searchResponseMetrics.incrementResponseCount(SearchResponseMetrics.ResponseCountTotalStatus.FAILURE);
2118+
searchResponseMetrics.incrementResponseCount(SearchResponseMetrics.ResponseCountTotalStatus.FAILURE, searchRequestAttributes);
21192119
if (collectCCSTelemetry) {
21202120
usageBuilder.setFailure(e);
21212121
recordTelemetry();

server/src/main/java/org/elasticsearch/cluster/ClusterInfo.java

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.elasticsearch.TransportVersion;
1313
import org.elasticsearch.TransportVersions;
14+
import org.elasticsearch.cluster.routing.ExpectedShardSizeEstimator;
1415
import org.elasticsearch.cluster.routing.RecoverySource;
1516
import org.elasticsearch.cluster.routing.ShardRouting;
1617
import org.elasticsearch.cluster.routing.UnassignedInfo;
@@ -45,7 +46,7 @@
4546
* <code>InternalClusterInfoService.shardIdentifierFromRouting(String)</code>
4647
* for the key used in the shardSizes map
4748
*/
48-
public class ClusterInfo implements ChunkedToXContent, Writeable {
49+
public class ClusterInfo implements ChunkedToXContent, Writeable, ExpectedShardSizeEstimator.ShardSizeProvider {
4950

5051
public static final ClusterInfo EMPTY = new ClusterInfo();
5152

@@ -289,33 +290,11 @@ public Map<ShardId, Double> getShardWriteLoads() {
289290
/**
290291
* Returns the shard size for the given shardId or <code>null</code> if that metric is not available.
291292
*/
293+
@Override
292294
public Long getShardSize(ShardId shardId, boolean primary) {
293295
return shardSizes.get(shardIdentifierFromRouting(shardId, primary));
294296
}
295297

296-
/**
297-
* Returns the shard size for the given shard routing or <code>null</code> if that metric is not available.
298-
*/
299-
public Long getShardSize(ShardRouting shardRouting) {
300-
return getShardSize(shardRouting.shardId(), shardRouting.primary());
301-
}
302-
303-
/**
304-
* Returns the shard size for the given shard routing or <code>defaultValue</code> it that metric is not available.
305-
*/
306-
public long getShardSize(ShardRouting shardRouting, long defaultValue) {
307-
Long shardSize = getShardSize(shardRouting);
308-
return shardSize == null ? defaultValue : shardSize;
309-
}
310-
311-
/**
312-
* Returns the shard size for the given shard routing or <code>defaultValue</code> it that metric is not available.
313-
*/
314-
public long getShardSize(ShardId shardId, boolean primary, long defaultValue) {
315-
Long shardSize = getShardSize(shardId, primary);
316-
return shardSize == null ? defaultValue : shardSize;
317-
}
318-
319298
/**
320299
* Returns the nodes absolute data-path the given shard is allocated on or <code>null</code> if the information is not available.
321300
*/

server/src/main/java/org/elasticsearch/cluster/ClusterInfoSimulator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void simulateShardStarted(ShardRouting shard) {
101101
var size = getExpectedShardSize(
102102
shard,
103103
shard.getExpectedShardSize(),
104-
getClusterInfo(),
104+
(shardId, primary) -> shardSizes.get(shardIdentifierFromRouting(shardId, primary)),
105105
allocation.snapshotShardSizeInfo(),
106106
project,
107107
allocation.routingTable(project.id())

server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.elasticsearch.common.settings.IndexScopedSettings;
3535
import org.elasticsearch.common.settings.Settings;
3636
import org.elasticsearch.common.util.set.Sets;
37+
import org.elasticsearch.core.Assertions;
3738
import org.elasticsearch.core.Nullable;
3839
import org.elasticsearch.core.TimeValue;
3940
import org.elasticsearch.core.Tuple;
@@ -818,7 +819,7 @@ void validateIndexTemplateV2(ProjectMetadata projectMetadata, String name, Compo
818819
var templateToValidate = indexTemplate.toBuilder().template(Template.builder(finalTemplate).settings(finalSettings)).build();
819820

820821
validate(name, templateToValidate, additionalSettings);
821-
validateDataStreamsStillReferenced(projectMetadata, name, templateToValidate);
822+
maybeValidateDataStreamsStillReferenced(projectMetadata, name, templateToValidate);
822823
validateLifecycle(componentTemplates, name, templateToValidate, globalRetentionSettings.get(false));
823824
validateDataStreamOptions(componentTemplates, name, templateToValidate, globalRetentionSettings.get(true));
824825

@@ -944,6 +945,43 @@ static void validateDataStreamOptions(
944945
}
945946
}
946947

948+
/**
949+
* Maybe runs {@link #validateDataStreamsStillReferenced} if it looks like the new composite template could change data stream coverage.
950+
*/
951+
private static void maybeValidateDataStreamsStillReferenced(
952+
ProjectMetadata project,
953+
String templateName,
954+
ComposableIndexTemplate newTemplate
955+
) {
956+
final ComposableIndexTemplate existingTemplate = project.templatesV2().get(templateName);
957+
final Settings existingSettings = Optional.ofNullable(existingTemplate)
958+
.map(ComposableIndexTemplate::template)
959+
.map(Template::settings)
960+
.orElse(Settings.EMPTY);
961+
final Settings newSettings = Optional.ofNullable(newTemplate)
962+
.map(ComposableIndexTemplate::template)
963+
.map(Template::settings)
964+
.orElse(Settings.EMPTY);
965+
// We check whether anything relevant has changed that could affect data stream coverage and return early if not.
966+
// These checks are based on the implementation of findV2Template and the data stream template check in this method.
967+
// If we're adding a new template, we do the full check in case this template's priority changes coverage.
968+
if (existingTemplate != null
969+
&& Objects.equals(existingTemplate.indexPatterns(), newTemplate.indexPatterns())
970+
&& Objects.equals(existingSettings.get(IndexMetadata.SETTING_INDEX_HIDDEN), newSettings.get(IndexMetadata.SETTING_INDEX_HIDDEN))
971+
&& Objects.equals(existingTemplate.getDataStreamTemplate() != null, newTemplate.getDataStreamTemplate() != null)
972+
&& Objects.equals(existingTemplate.priorityOrZero(), newTemplate.priorityOrZero())) {
973+
if (Assertions.ENABLED) {
974+
try {
975+
validateDataStreamsStillReferenced(project, templateName, newTemplate);
976+
} catch (IllegalArgumentException e) {
977+
assert false : "Data stream reference validation took a shortcut but the full check failed: " + e.getMessage();
978+
}
979+
}
980+
return;
981+
}
982+
validateDataStreamsStillReferenced(project, templateName, newTemplate);
983+
}
984+
947985
/**
948986
* Validate that by changing or adding {@code newTemplate}, there are
949987
* no unreferenced data streams. Note that this scenario is still possible
@@ -955,18 +993,16 @@ private static void validateDataStreamsStillReferenced(
955993
String templateName,
956994
ComposableIndexTemplate newTemplate
957995
) {
958-
final Set<String> dataStreams = project.dataStreams()
959-
.entrySet()
960-
.stream()
961-
.filter(entry -> entry.getValue().isSystem() == false)
962-
.map(Map.Entry::getKey)
963-
.collect(Collectors.toSet());
964-
965996
Function<Map<String, ComposableIndexTemplate>, Set<String>> findUnreferencedDataStreams = composableTemplates -> {
966997
final Set<String> unreferenced = new HashSet<>();
967998
// For each data stream that we have, see whether it's covered by a different
968999
// template (which is great), or whether it's now uncovered by any template
969-
for (String dataStream : dataStreams) {
1000+
for (var dataStreamEntry : project.dataStreams().entrySet()) {
1001+
// Exclude system data streams
1002+
if (dataStreamEntry.getValue().isSystem()) {
1003+
continue;
1004+
}
1005+
final String dataStream = dataStreamEntry.getKey();
9701006
final String matchingTemplate = findV2Template(project, composableTemplates.entrySet(), dataStream, false, false);
9711007
if (matchingTemplate == null) {
9721008
unreferenced.add(dataStream);

server/src/main/java/org/elasticsearch/cluster/routing/ExpectedShardSizeEstimator.java

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
package org.elasticsearch.cluster.routing;
1111

12-
import org.elasticsearch.cluster.ClusterInfo;
1312
import org.elasticsearch.cluster.metadata.IndexMetadata;
1413
import org.elasticsearch.cluster.metadata.Metadata;
1514
import org.elasticsearch.cluster.metadata.ProjectMetadata;
@@ -22,6 +21,36 @@
2221

2322
public class ExpectedShardSizeEstimator {
2423

24+
public interface ShardSizeProvider {
25+
/**
26+
* Returns the shard size for the given shardId or <code>null</code> if that metric is not available.
27+
*/
28+
Long getShardSize(ShardId shardId, boolean primary);
29+
30+
/**
31+
* Returns the shard size for the given shard routing or <code>null</code> if that metric is not available.
32+
*/
33+
default Long getShardSize(ShardRouting shardRouting) {
34+
return getShardSize(shardRouting.shardId(), shardRouting.primary());
35+
}
36+
37+
/**
38+
* Returns the shard size for the given shard routing or <code>defaultValue</code> it that metric is not available.
39+
*/
40+
default long getShardSize(ShardRouting shardRouting, long defaultValue) {
41+
final var shardSize = getShardSize(shardRouting);
42+
return shardSize == null ? defaultValue : shardSize;
43+
}
44+
45+
/**
46+
* Returns the shard size for the given shard routing or <code>defaultValue</code> it that metric is not available.
47+
*/
48+
default long getShardSize(ShardId shardId, boolean primary, long defaultValue) {
49+
final var shardSize = getShardSize(shardId, primary);
50+
return shardSize == null ? defaultValue : shardSize;
51+
}
52+
}
53+
2554
public static boolean shouldReserveSpaceForInitializingShard(ShardRouting shard, RoutingAllocation allocation) {
2655
return shouldReserveSpaceForInitializingShard(shard, allocation.metadata());
2756
}
@@ -69,7 +98,7 @@ public static boolean shouldReserveSpaceForInitializingShard(ShardRouting shard,
6998
public static long getExpectedShardSize(
7099
ShardRouting shard,
71100
long defaultValue,
72-
ClusterInfo clusterInfo,
101+
ShardSizeProvider shardSizeProvider,
73102
SnapshotShardSizeInfo snapshotShardSizeInfo,
74103
ProjectMetadata projectMetadata,
75104
RoutingTable routingTable
@@ -79,15 +108,15 @@ public static long getExpectedShardSize(
79108
&& shard.active() == false
80109
&& shard.recoverySource().getType() == RecoverySource.Type.LOCAL_SHARDS) {
81110
assert shard.primary() : "All replica shards are recovering from " + RecoverySource.Type.PEER;
82-
return getExpectedSizeOfResizedShard(shard, defaultValue, indexMetadata, clusterInfo, projectMetadata, routingTable);
111+
return getExpectedSizeOfResizedShard(shard, defaultValue, indexMetadata, shardSizeProvider, projectMetadata, routingTable);
83112
} else if (shard.active() == false && shard.recoverySource().getType() == RecoverySource.Type.SNAPSHOT) {
84113
assert shard.primary() : "All replica shards are recovering from " + RecoverySource.Type.PEER;
85114
return snapshotShardSizeInfo.getShardSize(shard, defaultValue);
86115
} else {
87-
var shardSize = clusterInfo.getShardSize(shard.shardId(), shard.primary());
116+
var shardSize = shardSizeProvider.getShardSize(shard.shardId(), shard.primary());
88117
if (shardSize == null && shard.primary() == false) {
89118
// derive replica size from corresponding primary
90-
shardSize = clusterInfo.getShardSize(shard.shardId(), true);
119+
shardSize = shardSizeProvider.getShardSize(shard.shardId(), true);
91120
}
92121
return shardSize == null ? defaultValue : shardSize;
93122
}
@@ -97,7 +126,7 @@ private static long getExpectedSizeOfResizedShard(
97126
ShardRouting shard,
98127
long defaultValue,
99128
IndexMetadata indexMetadata,
100-
ClusterInfo clusterInfo,
129+
ShardSizeProvider shardSizeProvider,
101130
ProjectMetadata projectMetadata,
102131
RoutingTable routingTable
103132
) {
@@ -120,7 +149,7 @@ private static long getExpectedSizeOfResizedShard(
120149
for (int i = 0; i < indexRoutingTable.size(); i++) {
121150
IndexShardRoutingTable shardRoutingTable = indexRoutingTable.shard(i);
122151
if (shardIds.contains(shardRoutingTable.shardId())) {
123-
targetShardSize += clusterInfo.getShardSize(shardRoutingTable.primaryShard(), 0);
152+
targetShardSize += shardSizeProvider.getShardSize(shardRoutingTable.primaryShard(), 0);
124153
}
125154
}
126155
}

server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/WriteLoadConstraintDecider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public Decision canAllocate(ShardRouting shardRouting, RoutingNode node, Routing
4343
return Decision.single(Decision.Type.YES, NAME, "Decider is disabled");
4444
}
4545

46+
// Never reject allocation of an unassigned shard
47+
if (shardRouting.assignedToNode() == false) {
48+
return Decision.single(Decision.Type.YES, NAME, "Shard is unassigned. Decider takes no action.");
49+
}
50+
4651
// Check whether the shard being relocated has any write load estimate. If it does not, then this decider has no opinion.
4752
var allShardWriteLoads = allocation.clusterInfo().getShardWriteLoads();
4853
var shardWriteLoad = allShardWriteLoads.get(shardRouting.shardId());

0 commit comments

Comments
 (0)