Skip to content

Commit 146b2a8

Browse files
jimczijavanna
andauthored
Add new x-pack endpoints to track the progress of a search asynchronously (#49931)
### High level view This change introduces a new API in x-pack basic that allows to track the progress of a search. Users can submit an asynchronous search through a new endpoint called `_async_search` that works exactly the same as the `_search` endpoint but instead of blocking and returning the final response when available, it returns a response after a provided `wait_for_completion` time. ```` # Submit an _async_search and waits up to 100ms for a final response GET my_index_pattern*/_async_search?wait_for_completion=100ms { "aggs": { "date_histogram": { "field": "@timestamp", "fixed_interval": "1h" } } } ```` If after 100ms the final response is not available, a `partial_response` is included in the body: ```` { "id": "9N3J1m4BgyzUDzqgC15b", "version": 1, "is_running": true, "is_partial": true, "response": { "_shards": { "total": 100, "successful": 5, "failed": 0 }, "total_hits": { "value": 1653433, "relation": "eq" }, "aggs": { ... } } } ```` The partial response contains the total number of requested shards, the number of shards that successfully returned and the number of shards that failed. It also contains the total hits as well as partial aggregations computed from the successful shards. To continue to monitor the progress of the search users can call the get `_async_search` API like the following: ```` GET _async_search/9N3J1m4BgyzUDzqgC15b/?wait_for_completion=100ms ```` That returns a new response that can contain the same partial response than the previous call if the search didn't progress, in such case the returned `version` should be the same. If new partial results are available, the version is incremented and the `partial_response` contains the updated progress. Finally if the response is fully available while or after waiting for completion, the `partial_response` is replaced by a `response` section that contains the usual _search response: ```` { "id": "9N3J1m4BgyzUDzqgC15b", "version": 10, "is_running": false, "response": { "is_partial": false, ... } } ```` ## Persistency Asynchronous search are stored in a restricted index called `.async-search` if they survive (still running) after the initial submit. Each request has a keep alive that defaults to 5 days but this value can be changed/updated any time: ````` GET my_index_pattern*/_async_search?wait_for_completion=100ms&keep_alive=10d ````` The default can be changed when submitting the search, the example above raises the default value for the search to `10d`. ````` GET _async_search/9N3J1m4BgyzUDzqgC15b/?wait_for_completion=100ms&keep_alive=10d ````` The time to live for a specific search can be extended when getting the progress/result. In the example above we extend the keep alive to 10 more days. A background service that runs only on the node that holds the first primary shard of the `async-search` index is responsible for deleting the expired results. It runs every hour but the expiration is also checked by running queries (if they take longer than the keep_alive) and when getting a result. Like a normal `_search`, if the http channel that is used to submit a request is closed before getting a response, the search is automatically cancelled. Note that this behavior is only for the submit API, subsequent GET requests will not cancel if they are closed. ## Resiliency Asynchronous search are not persistent, if the coordinator node crashes or is restarted during the search, the asynchronous search will stop. To know if the search is still running or not the response contains a field called `is_running` that indicates if the task is up or not. It is the responsibility of the user to resume an asynchronous search that didn't reach a final response by re-submitting the query. However final responses and failures are persisted in a system index that allows to retrieve a response even if the task finishes. ```` DELETE _async_search/9N3J1m4BgyzUDzqgC15b ```` The response is also not stored if the initial submit action returns a final response. This allows to not add any overhead to queries that completes within the initial `wait_for_completion`. ## Security The `.async-search` index is a restricted index (should be migrated to a system index in +8.0) that is accessible only through the async search APIs. These APIs also ensure that only the user that submitted the initial query can retrieve or delete the running search. Note that admins/superusers would still be able to cancel the search task through the task manager like any other tasks. Relates #49091 Co-authored-by: Luca Cavanna <[email protected]>
1 parent 0089805 commit 146b2a8

File tree

58 files changed

+4602
-104
lines changed

Some content is hidden

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

58 files changed

+4602
-104
lines changed

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

+7-6
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ abstract class AbstractSearchAsyncAction<Result extends SearchPhaseResult> exten
9090
private final SearchTimeProvider timeProvider;
9191
private final SearchResponse.Clusters clusters;
9292

93-
private final GroupShardsIterator<SearchShardIterator> toSkipShardsIts;
93+
protected final GroupShardsIterator<SearchShardIterator> toSkipShardsIts;
9494
protected final GroupShardsIterator<SearchShardIterator> shardsIts;
9595
private final int expectedTotalOps;
9696
private final AtomicInteger totalOps = new AtomicInteger();
@@ -385,7 +385,7 @@ private void onShardFailure(final int shardIndex, @Nullable ShardRouting shard,
385385
logger.trace(new ParameterizedMessage("{}: Failed to execute [{}]", shard, request), e);
386386
}
387387
}
388-
onShardGroupFailure(shardIndex, e);
388+
onShardGroupFailure(shardIndex, shardTarget, e);
389389
onPhaseDone();
390390
} else {
391391
final ShardRouting nextShard = shardIt.nextOrNull();
@@ -405,18 +405,19 @@ private void onShardFailure(final int shardIndex, @Nullable ShardRouting shard,
405405
shard != null ? shard.shortSummary() : shardIt.shardId(), request, lastShard), e);
406406
}
407407
}
408-
onShardGroupFailure(shardIndex, e);
408+
onShardGroupFailure(shardIndex, shardTarget, e);
409409
}
410410
}
411411
}
412412

413413
/**
414414
* Executed once for every {@link ShardId} that failed on all available shard routing.
415415
*
416-
* @param shardIndex the shard target that failed
417-
* @param exc the final failure reason
416+
* @param shardIndex the shard index that failed
417+
* @param shardTarget the last shard target for this failure
418+
* @param exc the last failure reason
418419
*/
419-
protected void onShardGroupFailure(int shardIndex, Exception exc) {}
420+
protected void onShardGroupFailure(int shardIndex, SearchShardTarget shardTarget, Exception exc) {}
420421

421422
/**
422423
* Executed once for every failed shard level request. This method is invoked before the next replica is tried for the given

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

+1-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.elasticsearch.common.util.concurrent.AtomicArray;
2323
import org.elasticsearch.search.SearchPhaseResult;
2424
import org.elasticsearch.search.SearchShardTarget;
25-
import org.elasticsearch.search.builder.SearchSourceBuilder;
2625
import org.elasticsearch.search.dfs.AggregatedDfs;
2726
import org.elasticsearch.search.dfs.DfsSearchResult;
2827
import org.elasticsearch.search.query.QuerySearchRequest;
@@ -72,8 +71,6 @@ public void run() throws IOException {
7271
final CountedCollector<SearchPhaseResult> counter = new CountedCollector<>(queryResult::consumeResult,
7372
resultList.size(),
7473
() -> context.executeNextPhase(this, nextPhaseFactory.apply(queryResult)), context);
75-
final SearchSourceBuilder sourceBuilder = context.getRequest().source();
76-
progressListener.notifyListShards(progressListener.searchShards(resultList), sourceBuilder == null || sourceBuilder.size() != 0);
7774
for (final DfsSearchResult dfsResult : resultList) {
7875
final SearchShardTarget searchShardTarget = dfsResult.getSearchShardTarget();
7976
Transport.Connection connection = context.getConnection(searchShardTarget.getClusterAlias(), searchShardTarget.getNodeId());
@@ -97,7 +94,7 @@ public void onFailure(Exception exception) {
9794
try {
9895
context.getLogger().debug(() -> new ParameterizedMessage("[{}] Failed to execute query phase",
9996
querySearchRequest.contextId()), exception);
100-
progressListener.notifyQueryFailure(shardIndex, exception);
97+
progressListener.notifyQueryFailure(shardIndex, searchShardTarget, exception);
10198
counter.onFailure(shardIndex, searchShardTarget, exception);
10299
} finally {
103100
// the query might not have been executed at all (for example because thread pool rejected

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

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.elasticsearch.cluster.ClusterState;
2525
import org.elasticsearch.cluster.routing.GroupShardsIterator;
2626
import org.elasticsearch.cluster.routing.ShardRouting;
27+
import org.elasticsearch.search.builder.SearchSourceBuilder;
2728
import org.elasticsearch.search.dfs.DfsSearchResult;
2829
import org.elasticsearch.search.internal.AliasFilter;
2930
import org.elasticsearch.transport.Transport;
@@ -51,6 +52,10 @@ final class SearchDfsQueryThenFetchAsyncAction extends AbstractSearchAsyncAction
5152
shardsIts, timeProvider, clusterState, task, new ArraySearchPhaseResults<>(shardsIts.size()),
5253
request.getMaxConcurrentShardRequests(), clusters);
5354
this.searchPhaseController = searchPhaseController;
55+
SearchProgressListener progressListener = task.getProgressListener();
56+
SearchSourceBuilder sourceBuilder = request.source();
57+
progressListener.notifyListShards(progressListener.searchShards(this.shardsIts),
58+
progressListener.searchShards(toSkipShardsIts), clusters, sourceBuilder == null || sourceBuilder.size() != 0);
5459
}
5560

5661
@Override

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -664,9 +664,9 @@ private synchronized void consumeInternal(QuerySearchResult querySearchResult) {
664664
}
665665
numReducePhases++;
666666
index = 1;
667-
if (hasAggs) {
667+
if (hasAggs || hasTopDocs) {
668668
progressListener.notifyPartialReduce(progressListener.searchShards(processedShards),
669-
topDocsStats.getTotalHits(), aggsBuffer[0], numReducePhases);
669+
topDocsStats.getTotalHits(), hasAggs ? aggsBuffer[0] : null, numReducePhases);
670670
}
671671
}
672672
final int i = index++;
@@ -696,7 +696,7 @@ public ReducedQueryPhase reduce() {
696696
ReducedQueryPhase reducePhase = controller.reducedQueryPhase(results.asList(),
697697
getRemainingAggs(), getRemainingTopDocs(), topDocsStats, numReducePhases, false, performFinalReduce);
698698
progressListener.notifyReduce(progressListener.searchShards(results.asList()),
699-
reducePhase.totalHits, reducePhase.aggregations);
699+
reducePhase.totalHits, reducePhase.aggregations, reducePhase.numReducePhases);
700700
return reducePhase;
701701
}
702702

@@ -751,7 +751,8 @@ ReducedQueryPhase reduce() {
751751
List<SearchPhaseResult> resultList = results.asList();
752752
final ReducedQueryPhase reducePhase =
753753
reducedQueryPhase(resultList, isScrollRequest, trackTotalHitsUpTo, request.isFinalReduce());
754-
listener.notifyReduce(listener.searchShards(resultList), reducePhase.totalHits, reducePhase.aggregations);
754+
listener.notifyReduce(listener.searchShards(resultList), reducePhase.totalHits,
755+
reducePhase.aggregations, reducePhase.numReducePhases);
755756
return reducePhase;
756757
}
757758
};

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

+22-17
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.apache.logging.log4j.Logger;
2424
import org.apache.logging.log4j.message.ParameterizedMessage;
2525
import org.apache.lucene.search.TotalHits;
26+
import org.elasticsearch.action.search.SearchResponse.Clusters;
2627
import org.elasticsearch.cluster.routing.GroupShardsIterator;
2728
import org.elasticsearch.search.SearchPhaseResult;
2829
import org.elasticsearch.search.SearchShardTarget;
@@ -48,24 +49,27 @@ abstract class SearchProgressListener {
4849
* Executed when shards are ready to be queried.
4950
*
5051
* @param shards The list of shards to query.
52+
* @param skippedShards The list of skipped shards.
53+
* @param clusters The statistics for remote clusters included in the search.
5154
* @param fetchPhase <code>true</code> if the search needs a fetch phase, <code>false</code> otherwise.
5255
**/
53-
public void onListShards(List<SearchShard> shards, boolean fetchPhase) {}
56+
public void onListShards(List<SearchShard> shards, List<SearchShard> skippedShards, Clusters clusters, boolean fetchPhase) {}
5457

5558
/**
5659
* Executed when a shard returns a query result.
5760
*
58-
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards(List, boolean)} )}.
61+
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards} )}.
5962
*/
6063
public void onQueryResult(int shardIndex) {}
6164

6265
/**
6366
* Executed when a shard reports a query failure.
6467
*
65-
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards(List, boolean)})}.
68+
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards})}.
69+
* @param shardTarget The last shard target that thrown an exception.
6670
* @param exc The cause of the failure.
6771
*/
68-
public void onQueryFailure(int shardIndex, Exception exc) {}
72+
public void onQueryFailure(int shardIndex, SearchShardTarget shardTarget, Exception exc) {}
6973

7074
/**
7175
* Executed when a partial reduce is created. The number of partial reduce can be controlled via
@@ -74,38 +78,39 @@ public void onQueryFailure(int shardIndex, Exception exc) {}
7478
* @param shards The list of shards that are part of this reduce.
7579
* @param totalHits The total number of hits in this reduce.
7680
* @param aggs The partial result for aggregations.
77-
* @param version The version number for this reduce.
81+
* @param reducePhase The version number for this reduce.
7882
*/
79-
public void onPartialReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int version) {}
83+
public void onPartialReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {}
8084

8185
/**
8286
* Executed once when the final reduce is created.
8387
*
8488
* @param shards The list of shards that are part of this reduce.
8589
* @param totalHits The total number of hits in this reduce.
8690
* @param aggs The final result for aggregations.
91+
* @param reducePhase The version number for this reduce.
8792
*/
88-
public void onReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs) {}
93+
public void onReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {}
8994

9095
/**
9196
* Executed when a shard returns a fetch result.
9297
*
93-
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards(List, boolean)})}.
98+
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards})}.
9499
*/
95100
public void onFetchResult(int shardIndex) {}
96101

97102
/**
98103
* Executed when a shard reports a fetch failure.
99104
*
100-
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards(List, boolean)})}.
105+
* @param shardIndex The index of the shard in the list provided by {@link SearchProgressListener#onListShards})}.
101106
* @param exc The cause of the failure.
102107
*/
103108
public void onFetchFailure(int shardIndex, Exception exc) {}
104109

105-
final void notifyListShards(List<SearchShard> shards, boolean fetchPhase) {
110+
final void notifyListShards(List<SearchShard> shards, List<SearchShard> skippedShards, Clusters clusters, boolean fetchPhase) {
106111
this.shards = shards;
107112
try {
108-
onListShards(shards, fetchPhase);
113+
onListShards(shards, skippedShards, clusters, fetchPhase);
109114
} catch (Exception e) {
110115
logger.warn(() -> new ParameterizedMessage("Failed to execute progress listener on list shards"), e);
111116
}
@@ -120,26 +125,26 @@ final void notifyQueryResult(int shardIndex) {
120125
}
121126
}
122127

123-
final void notifyQueryFailure(int shardIndex, Exception exc) {
128+
final void notifyQueryFailure(int shardIndex, SearchShardTarget shardTarget, Exception exc) {
124129
try {
125-
onQueryFailure(shardIndex, exc);
130+
onQueryFailure(shardIndex, shardTarget, exc);
126131
} catch (Exception e) {
127132
logger.warn(() -> new ParameterizedMessage("[{}] Failed to execute progress listener on query failure",
128133
shards.get(shardIndex)), e);
129134
}
130135
}
131136

132-
final void notifyPartialReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int version) {
137+
final void notifyPartialReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
133138
try {
134-
onPartialReduce(shards, totalHits, aggs, version);
139+
onPartialReduce(shards, totalHits, aggs, reducePhase);
135140
} catch (Exception e) {
136141
logger.warn(() -> new ParameterizedMessage("Failed to execute progress listener on partial reduce"), e);
137142
}
138143
}
139144

140-
final void notifyReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs) {
145+
final void notifyReduce(List<SearchShard> shards, TotalHits totalHits, InternalAggregations aggs, int reducePhase) {
141146
try {
142-
onReduce(shards, totalHits, aggs);
147+
onReduce(shards, totalHits, aggs, reducePhase);
143148
} catch (Exception e) {
144149
logger.warn(() -> new ParameterizedMessage("Failed to execute progress listener on reduce"), e);
145150
}

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.elasticsearch.cluster.routing.GroupShardsIterator;
2626
import org.elasticsearch.cluster.routing.ShardRouting;
2727
import org.elasticsearch.search.SearchPhaseResult;
28+
import org.elasticsearch.search.SearchShardTarget;
2829
import org.elasticsearch.search.builder.SearchSourceBuilder;
2930
import org.elasticsearch.search.internal.AliasFilter;
3031
import org.elasticsearch.transport.Transport;
@@ -57,7 +58,7 @@ final class SearchQueryThenFetchAsyncAction extends AbstractSearchAsyncAction<Se
5758
final SearchProgressListener progressListener = task.getProgressListener();
5859
final SearchSourceBuilder sourceBuilder = request.source();
5960
progressListener.notifyListShards(progressListener.searchShards(this.shardsIts),
60-
sourceBuilder == null || sourceBuilder.size() != 0);
61+
progressListener.searchShards(toSkipShardsIts), clusters, sourceBuilder == null || sourceBuilder.size() != 0);
6162
}
6263

6364
protected void executePhaseOnShard(final SearchShardIterator shardIt, final ShardRouting shard,
@@ -67,8 +68,8 @@ protected void executePhaseOnShard(final SearchShardIterator shardIt, final Shar
6768
}
6869

6970
@Override
70-
protected void onShardGroupFailure(int shardIndex, Exception exc) {
71-
progressListener.notifyQueryFailure(shardIndex, exc);
71+
protected void onShardGroupFailure(int shardIndex, SearchShardTarget shardTarget, Exception exc) {
72+
progressListener.notifyQueryFailure(shardIndex, shardTarget, exc);
7273
}
7374

7475
@Override

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.elasticsearch.search.Scroll;
3434
import org.elasticsearch.search.builder.SearchSourceBuilder;
3535
import org.elasticsearch.search.internal.SearchContext;
36-
import org.elasticsearch.tasks.Task;
3736
import org.elasticsearch.tasks.TaskId;
3837

3938
import java.io.IOException;
@@ -56,9 +55,9 @@
5655
* @see org.elasticsearch.client.Client#search(SearchRequest)
5756
* @see SearchResponse
5857
*/
59-
public final class SearchRequest extends ActionRequest implements IndicesRequest.Replaceable {
58+
public class SearchRequest extends ActionRequest implements IndicesRequest.Replaceable {
6059

61-
private static final ToXContent.Params FORMAT_PARAMS = new ToXContent.MapParams(Collections.singletonMap("pretty", "false"));
60+
public static final ToXContent.Params FORMAT_PARAMS = new ToXContent.MapParams(Collections.singletonMap("pretty", "false"));
6261

6362
public static final int DEFAULT_PRE_FILTER_SHARD_SIZE = 128;
6463
public static final int DEFAULT_BATCHED_REDUCE_SIZE = 512;
@@ -560,7 +559,7 @@ public boolean isSuggestOnly() {
560559
}
561560

562561
@Override
563-
public Task createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
562+
public SearchTask createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
564563
// generating description in a lazy way since source can be quite big
565564
return new SearchTask(id, type, action, null, parentTaskId, headers) {
566565
@Override

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public SearchRequestBuilder setVersion(boolean version) {
213213
sourceBuilder().version(version);
214214
return this;
215215
}
216-
216+
217217
/**
218218
* Should each {@link org.elasticsearch.search.SearchHit} be returned with the
219219
* sequence number and primary term of the last modification of the document.

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

+4
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ public RestStatus status() {
113113
return RestStatus.status(successfulShards, totalShards, shardFailures);
114114
}
115115

116+
public SearchResponseSections getInternalResponse() {
117+
return internalResponse;
118+
}
119+
116120
/**
117121
* The search hits.
118122
*/

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class SearchShard implements Comparable<SearchShard> {
3434
private final String clusterAlias;
3535
private final ShardId shardId;
3636

37-
SearchShard(@Nullable String clusterAlias, ShardId shardId) {
37+
public SearchShard(@Nullable String clusterAlias, ShardId shardId) {
3838
this.clusterAlias = clusterAlias;
3939
this.shardId = shardId;
4040
}

server/src/main/java/org/elasticsearch/client/node/NodeClient.java

-38
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@
2323
import org.elasticsearch.action.ActionRequest;
2424
import org.elasticsearch.action.ActionResponse;
2525
import org.elasticsearch.action.ActionType;
26-
import org.elasticsearch.action.search.SearchAction;
27-
import org.elasticsearch.action.search.SearchRequest;
28-
import org.elasticsearch.action.search.SearchResponse;
29-
import org.elasticsearch.action.search.SearchTask;
30-
import org.elasticsearch.action.search.SearchProgressActionListener;
31-
import org.elasticsearch.action.search.TransportSearchAction;
3226
import org.elasticsearch.action.support.TransportAction;
3327
import org.elasticsearch.client.Client;
3428
import org.elasticsearch.client.support.AbstractClient;
@@ -108,38 +102,6 @@ > Task executeLocally(ActionType<Response> action, Request request, TaskListener
108102
listener::onResponse, listener::onFailure);
109103
}
110104

111-
/**
112-
* Execute a {@link SearchRequest} locally and track the progress of the request through
113-
* a {@link SearchProgressActionListener}.
114-
*/
115-
public SearchTask executeSearchLocally(SearchRequest request, SearchProgressActionListener listener) {
116-
// we cannot track the progress if remote cluster requests are splitted.
117-
request.setCcsMinimizeRoundtrips(false);
118-
TransportSearchAction action = (TransportSearchAction) actions.get(SearchAction.INSTANCE);
119-
SearchTask task = (SearchTask) taskManager.register("transport", action.actionName, request);
120-
task.setProgressListener(listener);
121-
action.execute(task, request, new ActionListener<>() {
122-
@Override
123-
public void onResponse(SearchResponse response) {
124-
try {
125-
taskManager.unregister(task);
126-
} finally {
127-
listener.onResponse(response);
128-
}
129-
}
130-
131-
@Override
132-
public void onFailure(Exception e) {
133-
try {
134-
taskManager.unregister(task);
135-
} finally {
136-
listener.onFailure(e);
137-
}
138-
}
139-
});
140-
return task;
141-
}
142-
143105
/**
144106
* The id of the local {@link DiscoveryNode}. Useful for generating task ids from tasks returned by
145107
* {@link #executeLocally(ActionType, ActionRequest, TaskListener)}.

server/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public static void parseSearchRequest(SearchRequest searchRequest, RestRequest r
164164
searchRequest.routing(request.param("routing"));
165165
searchRequest.preference(request.param("preference"));
166166
searchRequest.indicesOptions(IndicesOptions.fromRequest(request, searchRequest.indicesOptions()));
167-
searchRequest.setCcsMinimizeRoundtrips(request.paramAsBoolean("ccs_minimize_roundtrips", true));
167+
searchRequest.setCcsMinimizeRoundtrips(request.paramAsBoolean("ccs_minimize_roundtrips", searchRequest.isCcsMinimizeRoundtrips()));
168168

169169
checkRestTotalHits(request, searchRequest);
170170
}

0 commit comments

Comments
 (0)