Skip to content

Commit c3d2417

Browse files
javannajrodewig
andauthored
Cumulative backport of async search changes (#53635)
* Submit async search to work only with POST (#53368) Currently the submit async search API can be called using both GET and POST at REST, but given that it submits a call and creates internal state, POST should be the only allowed method. * Refine SearchProgressListener internal API (#53373) The following cumulative improvements have been made: - rename `onReduce` and `notifyReduce` to `onFinalReduce` and `notifyFinalReduce` - add unit test for `SearchShard` - on* methods in `SearchProgressListener` shouldn't need to be public as they should never be called directly, they only need to be overridden hence they can be made protected. They are actually called directly from a test which required some adapting, like making `AsyncSearchTask.Listener` class package private instead of private - Instead of overriding `getProgressListener` in `AsyncSearchTask`, as it feels weird to override a getter method, added a specific method that allows to retrieve the Listener directly without needing to cast it. Made the getter and setter for the listener final in the base class. - rename `SearchProgressListener#searchShards` methods to `buildSearchShards` and make it static given that it accesses no instance members - make `SearchShard` and `SearchShardTask` classes final * Move async search yaml tests to x-pack yaml test folder (#53537) The yaml tests for async search currently sit in its qa folder. There is no reason though for them to live in a separate folder as they don't require particular setup. This commit moves them to the main folder together with the other x-pack yaml tests so that they will be run by the client test runners too. * [DOCS] Add temporary redirect for async-search (#53454) The following API spec files contain a link to a not-yet-created async search docs page: * [async_search.delete.json][0] * [async_search.get.json][1] * [async_search.submit.json][2] The Elaticsearch-js client uses these spec files to create their docs. This created a broken link in the Elaticsearch-js docs, which has broken the docs build. This PR adds a temporary redirect for the docs page. This redirect should be removed when the actual API docs are added. [0]: https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/src/test/resources/rest-api-spec/api/async_search.delete.json [1]: https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/src/test/resources/rest-api-spec/api/async_search.get.json [2]: https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/src/test/resources/rest-api-spec/api/async_search.submit.json Co-authored-by: James Rodewig <[email protected]>
1 parent 9845dbb commit c3d2417

File tree

23 files changed

+151
-182
lines changed

23 files changed

+151
-182
lines changed

docs/reference/redirects.asciidoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,3 +602,8 @@ See <<slm-api-stop>>.
602602
=== How {ccs} works
603603

604604
See <<ccs-gateway-seed-nodes>> and <<ccs-min-roundtrips>>.
605+
606+
[role="exclude",id="async-search"]
607+
=== Asynchronous search
608+
609+
coming::[7.x]

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ final class SearchDfsQueryThenFetchAsyncAction extends AbstractSearchAsyncAction
5454
this.searchPhaseController = searchPhaseController;
5555
SearchProgressListener progressListener = task.getProgressListener();
5656
SearchSourceBuilder sourceBuilder = request.source();
57-
progressListener.notifyListShards(progressListener.searchShards(this.shardsIts),
58-
progressListener.searchShards(toSkipShardsIts), clusters, sourceBuilder == null || sourceBuilder.size() != 0);
57+
progressListener.notifyListShards(SearchProgressListener.buildSearchShards(this.shardsIts),
58+
SearchProgressListener.buildSearchShards(toSkipShardsIts), clusters, sourceBuilder == null || sourceBuilder.size() != 0);
5959
}
6060

6161
@Override

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -679,8 +679,8 @@ private synchronized void consumeInternal(QuerySearchResult querySearchResult) {
679679
numReducePhases++;
680680
index = 1;
681681
if (hasAggs || hasTopDocs) {
682-
progressListener.notifyPartialReduce(progressListener.searchShards(processedShards),
683-
topDocsStats.getTotalHits(), hasAggs ? aggsBuffer[0] : null, numReducePhases);
682+
progressListener.notifyPartialReduce(SearchProgressListener.buildSearchShards(processedShards),
683+
topDocsStats.getTotalHits(), hasAggs ? aggsBuffer[0] : null, numReducePhases);
684684
}
685685
}
686686
final int i = index++;
@@ -710,7 +710,7 @@ public ReducedQueryPhase reduce() {
710710
ReducedQueryPhase reducePhase = controller.reducedQueryPhase(results.asList(),
711711
getRemainingAggs(), getRemainingTopDocs(), topDocsStats, numReducePhases, false,
712712
aggReduceContextBuilder, performFinalReduce);
713-
progressListener.notifyReduce(progressListener.searchShards(results.asList()),
713+
progressListener.notifyFinalReduce(SearchProgressListener.buildSearchShards(results.asList()),
714714
reducePhase.totalHits, reducePhase.aggregations, reducePhase.numReducePhases);
715715
return reducePhase;
716716
}
@@ -767,8 +767,8 @@ ReducedQueryPhase reduce() {
767767
List<SearchPhaseResult> resultList = results.asList();
768768
final ReducedQueryPhase reducePhase =
769769
reducedQueryPhase(resultList, isScrollRequest, trackTotalHitsUpTo, aggReduceContextBuilder, request.isFinalReduce());
770-
listener.notifyReduce(listener.searchShards(resultList), reducePhase.totalHits,
771-
reducePhase.aggregations, reducePhase.numReducePhases);
770+
listener.notifyFinalReduce(SearchProgressListener.buildSearchShards(resultList),
771+
reducePhase.totalHits, reducePhase.aggregations, reducePhase.numReducePhases);
772772
return reducePhase;
773773
}
774774
};

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ abstract class SearchProgressListener {
5454
* @param clusters The statistics for remote clusters included in the search.
5555
* @param fetchPhase <code>true</code> if the search needs a fetch phase, <code>false</code> otherwise.
5656
**/
57-
public void onListShards(List<SearchShard> shards, List<SearchShard> skippedShards, Clusters clusters, boolean fetchPhase) {}
57+
protected void onListShards(List<SearchShard> shards, List<SearchShard> skippedShards, Clusters clusters, boolean fetchPhase) {}
5858

5959
/**
6060
* Executed when a shard returns a query result.
6161
*
6262
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards} )}.
6363
*/
64-
public void onQueryResult(int shardIndex) {}
64+
protected void onQueryResult(int shardIndex) {}
6565

6666
/**
6767
* Executed when a shard reports a query failure.
@@ -70,7 +70,7 @@ public void onQueryResult(int shardIndex) {}
7070
* @param shardTarget The last shard target that thrown an exception.
7171
* @param exc The cause of the failure.
7272
*/
73-
public void onQueryFailure(int shardIndex, SearchShardTarget shardTarget, Exception exc) {}
73+
protected void onQueryFailure(int shardIndex, SearchShardTarget shardTarget, Exception exc) {}
7474

7575
/**
7676
* Executed when a partial reduce is created. The number of partial reduce can be controlled via
@@ -81,7 +81,7 @@ public void onQueryFailure(int shardIndex, SearchShardTarget shardTarget, Except
8181
* @param aggs The partial result for aggregations.
8282
* @param reducePhase The version number for this reduce.
8383
*/
84-
public void onPartialReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {}
84+
protected void onPartialReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {}
8585

8686
/**
8787
* Executed once when the final reduce is created.
@@ -91,22 +91,22 @@ public void onPartialReduce(List<SearchShard> shards, TotalHits totalHits, Inter
9191
* @param aggs The final result for aggregations.
9292
* @param reducePhase The version number for this reduce.
9393
*/
94-
public void onReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {}
94+
protected void onFinalReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {}
9595

9696
/**
9797
* Executed when a shard returns a fetch result.
9898
*
9999
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards})}.
100100
*/
101-
public void onFetchResult(int shardIndex) {}
101+
protected void onFetchResult(int shardIndex) {}
102102

103103
/**
104104
* Executed when a shard reports a fetch failure.
105105
*
106106
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards})}.
107107
* @param exc The cause of the failure.
108108
*/
109-
public void onFetchFailure(int shardIndex, Exception exc) {}
109+
protected void onFetchFailure(int shardIndex, Exception exc) {}
110110

111111
final void notifyListShards(List<SearchShard> shards, List<SearchShard> skippedShards, Clusters clusters, boolean fetchPhase) {
112112
this.shards = shards;
@@ -143,9 +143,9 @@ final void notifyPartialReduce(List<SearchShard> shards, TotalHits totalHits, In
143143
}
144144
}
145145

146-
final void notifyReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
146+
protected final void notifyFinalReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
147147
try {
148-
onReduce(shards, totalHits, aggs, reducePhase);
148+
onFinalReduce(shards, totalHits, aggs, reducePhase);
149149
} catch (Exception e) {
150150
logger.warn(() -> new ParameterizedMessage("Failed to execute progress listener on reduce"), e);
151151
}
@@ -169,25 +169,25 @@ final void notifyFetchFailure(int shardIndex, Exception exc) {
169169
}
170170
}
171171

172-
final List<SearchShard> searchShards(List<? extends SearchPhaseResult> results) {
173-
List<SearchShard> lst = results.stream()
172+
static List<SearchShard> buildSearchShards(List<? extends SearchPhaseResult> results) {
173+
List<SearchShard> lst = results.stream()
174174
.filter(Objects::nonNull)
175175
.map(SearchPhaseResult::getSearchShardTarget)
176176
.map(e -> new SearchShard(e.getClusterAlias(), e.getShardId()))
177177
.collect(Collectors.toList());
178178
return Collections.unmodifiableList(lst);
179179
}
180180

181-
final List<SearchShard> searchShards(SearchShardTarget[] results) {
182-
List<SearchShard> lst = Arrays.stream(results)
181+
static List<SearchShard> buildSearchShards(SearchShardTarget[] results) {
182+
List<SearchShard> lst = Arrays.stream(results)
183183
.filter(Objects::nonNull)
184184
.map(e -> new SearchShard(e.getClusterAlias(), e.getShardId()))
185185
.collect(Collectors.toList());
186186
return Collections.unmodifiableList(lst);
187187
}
188188

189-
final List<SearchShard> searchShards(GroupShardsIterator<SearchShardIterator> its) {
190-
List<SearchShard> lst = StreamSupport.stream(its.spliterator(), false)
189+
static List<SearchShard> buildSearchShards(GroupShardsIterator<SearchShardIterator> its) {
190+
List<SearchShard> lst = StreamSupport.stream(its.spliterator(), false)
191191
.map(e -> new SearchShard(e.getClusterAlias(), e.shardId()))
192192
.collect(Collectors.toList());
193193
return Collections.unmodifiableList(lst);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ final class SearchQueryThenFetchAsyncAction extends AbstractSearchAsyncAction<Se
5757
this.progressListener = task.getProgressListener();
5858
final SearchProgressListener progressListener = task.getProgressListener();
5959
final SearchSourceBuilder sourceBuilder = request.source();
60-
progressListener.notifyListShards(progressListener.searchShards(this.shardsIts),
61-
progressListener.searchShards(toSkipShardsIts), clusters, sourceBuilder == null || sourceBuilder.size() != 0);
60+
progressListener.notifyListShards(SearchProgressListener.buildSearchShards(this.shardsIts),
61+
SearchProgressListener.buildSearchShards(toSkipShardsIts), clusters, sourceBuilder == null || sourceBuilder.size() != 0);
6262
}
6363

6464
protected void executePhaseOnShard(final SearchShardIterator shardIt, final ShardRouting shard,

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* A class that encapsulates the {@link ShardId} and the cluster alias
3030
* of a shard used during the search action.
3131
*/
32-
public class SearchShard implements Comparable<SearchShard> {
32+
public final class SearchShard implements Comparable<SearchShard> {
3333
@Nullable
3434
private final String clusterAlias;
3535
private final ShardId shardId;
@@ -40,8 +40,7 @@ public SearchShard(@Nullable String clusterAlias, ShardId shardId) {
4040
}
4141

4242
/**
43-
* Return the cluster alias if the shard is on a remote cluster and <code>null</code>
44-
* otherwise (local).
43+
* Return the cluster alias if we are executing a cross cluster search request, <code>null</code> otherwise.
4544
*/
4645
@Nullable
4746
public String getClusterAlias() {
@@ -51,7 +50,6 @@ public String getClusterAlias() {
5150
/**
5251
* Return the {@link ShardId} of this shard.
5352
*/
54-
@Nullable
5553
public ShardId getShardId() {
5654
return shardId;
5755
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,4 @@ public SearchShardTask(long id, String type, String action, String description,
4040
public boolean shouldCancelChildrenOnCancellation() {
4141
return false;
4242
}
43-
4443
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ public SearchTask(long id, String type, String action, String description, TaskI
3737
/**
3838
* Attach a {@link SearchProgressListener} to this task.
3939
*/
40-
public void setProgressListener(SearchProgressListener progressListener) {
40+
public final void setProgressListener(SearchProgressListener progressListener) {
4141
this.progressListener = progressListener;
4242
}
4343

4444
/**
4545
* Return the {@link SearchProgressListener} attached to this task.
4646
*/
47-
public SearchProgressListener getProgressListener() {
47+
public final SearchProgressListener getProgressListener() {
4848
return progressListener;
4949
}
5050

server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ public void onPartialReduce(List<SearchShard> shards, TotalHits totalHits, Inter
847847
}
848848

849849
@Override
850-
public void onReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
850+
public void onFinalReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
851851
totalHitsListener.set(totalHits);
852852
finalAggsListener.set(aggs);
853853
numReduceListener.incrementAndGet();

server/src/test/java/org/elasticsearch/action/search/SearchProgressActionListenerIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public void onPartialReduce(List<SearchShard> shards, TotalHits totalHits, Inter
178178
}
179179

180180
@Override
181-
public void onReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
181+
public void onFinalReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
182182
numReduces.incrementAndGet();
183183
}
184184

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.action.search;
21+
22+
import org.elasticsearch.index.Index;
23+
import org.elasticsearch.index.shard.ShardId;
24+
import org.elasticsearch.test.ESTestCase;
25+
import org.elasticsearch.test.EqualsHashCodeTestUtils;
26+
27+
import java.util.ArrayList;
28+
import java.util.Collections;
29+
import java.util.List;
30+
31+
public class SearchShardTests extends ESTestCase {
32+
33+
public void testEqualsAndHashcode() {
34+
String index = randomAlphaOfLengthBetween(5, 10);
35+
SearchShard searchShard = new SearchShard(randomBoolean() ? null : randomAlphaOfLengthBetween(3, 10),
36+
new ShardId(index, index + "-uuid", randomIntBetween(0, 1024)));
37+
EqualsHashCodeTestUtils.checkEqualsAndHashCode(searchShard,
38+
s -> new SearchShard(s.getClusterAlias(), s.getShardId()),
39+
s -> {
40+
if (randomBoolean()) {
41+
return new SearchShard(s.getClusterAlias() == null ? randomAlphaOfLengthBetween(3, 10) : null, s.getShardId());
42+
} else {
43+
String indexName = s.getShardId().getIndexName();
44+
int shardId = s.getShardId().getId();
45+
if (randomBoolean()) {
46+
indexName += randomAlphaOfLength(5);
47+
} else {
48+
shardId += randomIntBetween(1, 1024);
49+
}
50+
return new SearchShard(s.getClusterAlias(), new ShardId(indexName, indexName + "-uuid", shardId));
51+
}
52+
});
53+
}
54+
55+
public void testCompareTo() {
56+
List<SearchShard> searchShards = new ArrayList<>();
57+
Index index0 = new Index("index0", "index0-uuid");
58+
Index index1 = new Index("index1", "index1-uuid");
59+
searchShards.add(new SearchShard(null, new ShardId(index0, 0)));
60+
searchShards.add(new SearchShard(null, new ShardId(index1, 0)));
61+
searchShards.add(new SearchShard(null, new ShardId(index0, 1)));
62+
searchShards.add(new SearchShard(null, new ShardId(index1, 1)));
63+
searchShards.add(new SearchShard(null, new ShardId(index0, 2)));
64+
searchShards.add(new SearchShard(null, new ShardId(index1, 2)));
65+
searchShards.add(new SearchShard("", new ShardId(index0, 0)));
66+
searchShards.add(new SearchShard("", new ShardId(index1, 0)));
67+
searchShards.add(new SearchShard("", new ShardId(index0, 1)));
68+
searchShards.add(new SearchShard("", new ShardId(index1, 1)));
69+
70+
searchShards.add(new SearchShard("remote0", new ShardId(index0, 0)));
71+
searchShards.add(new SearchShard("remote0", new ShardId(index1, 0)));
72+
searchShards.add(new SearchShard("remote0", new ShardId(index0, 1)));
73+
searchShards.add(new SearchShard("remote0", new ShardId(index0, 2)));
74+
searchShards.add(new SearchShard("remote1", new ShardId(index0, 0)));
75+
searchShards.add(new SearchShard("remote1", new ShardId(index1, 0)));
76+
searchShards.add(new SearchShard("remote1", new ShardId(index0, 1)));
77+
searchShards.add(new SearchShard("remote1", new ShardId(index1, 1)));
78+
79+
List<SearchShard> sorted = new ArrayList<>(searchShards);
80+
Collections.sort(sorted);
81+
assertEquals(searchShards, sorted);
82+
}
83+
}

x-pack/plugin/async-search/qa/rest/build.gradle

Lines changed: 0 additions & 30 deletions
This file was deleted.

x-pack/plugin/async-search/qa/rest/src/test/java/org/elasticsearch/xpack/search/AsyncSearchRestIT.java

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)