Skip to content

Commit 572bb40

Browse files
authored
Enable cancellation for msearch requests (#61337)
Today multi-search requests are not cancellable because we create regular tasks instead of cancellable ones for them.
1 parent 2a49ba3 commit 572bb40

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

server/src/internalClusterTest/java/org/elasticsearch/search/SearchCancellationIT.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@
2020
package org.elasticsearch.search;
2121

2222
import org.apache.logging.log4j.LogManager;
23+
import org.elasticsearch.ExceptionsHelper;
2324
import org.elasticsearch.action.ActionFuture;
2425
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksResponse;
2526
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
2627
import org.elasticsearch.action.bulk.BulkRequestBuilder;
28+
import org.elasticsearch.action.search.MultiSearchAction;
29+
import org.elasticsearch.action.search.MultiSearchResponse;
2730
import org.elasticsearch.action.search.SearchAction;
2831
import org.elasticsearch.action.search.SearchPhaseExecutionException;
2932
import org.elasticsearch.action.search.SearchResponse;
3033
import org.elasticsearch.action.search.SearchScrollAction;
34+
import org.elasticsearch.action.search.ShardSearchFailure;
3135
import org.elasticsearch.action.support.WriteRequest;
3236
import org.elasticsearch.common.Strings;
3337
import org.elasticsearch.common.settings.Settings;
@@ -38,6 +42,7 @@
3842
import org.elasticsearch.script.Script;
3943
import org.elasticsearch.script.ScriptType;
4044
import org.elasticsearch.search.lookup.LeafFieldsLookup;
45+
import org.elasticsearch.tasks.TaskCancelledException;
4146
import org.elasticsearch.tasks.TaskInfo;
4247
import org.elasticsearch.test.ESIntegTestCase;
4348

@@ -52,10 +57,12 @@
5257

5358
import static org.elasticsearch.index.query.QueryBuilders.scriptQuery;
5459
import static org.elasticsearch.search.SearchCancellationIT.ScriptedBlockPlugin.SCRIPT_NAME;
60+
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures;
5561
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
5662
import static org.hamcrest.Matchers.equalTo;
5763
import static org.hamcrest.Matchers.greaterThan;
5864
import static org.hamcrest.Matchers.hasSize;
65+
import static org.hamcrest.Matchers.notNullValue;
5966

6067
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.SUITE)
6168
public class SearchCancellationIT extends ESIntegTestCase {
@@ -245,6 +252,26 @@ public void testCancellationOfScrollSearchesOnFollowupRequests() throws Exceptio
245252
client().prepareClearScroll().addScrollId(scrollId).get();
246253
}
247254

255+
public void testCancelMultiSearch() throws Exception {
256+
List<ScriptedBlockPlugin> plugins = initBlockFactory();
257+
indexTestData();
258+
ActionFuture<MultiSearchResponse> msearchResponse = client().prepareMultiSearch().add(client().prepareSearch("test")
259+
.addScriptField("test_field", new Script(ScriptType.INLINE, "mockscript", SCRIPT_NAME, Collections.emptyMap())))
260+
.execute();
261+
awaitForBlock(plugins);
262+
cancelSearch(MultiSearchAction.NAME);
263+
disableBlocks(plugins);
264+
for (MultiSearchResponse.Item item : msearchResponse.actionGet()) {
265+
if (item.getFailure() != null) {
266+
assertThat(ExceptionsHelper.unwrap(item.getFailure(), TaskCancelledException.class), notNullValue());
267+
} else {
268+
assertFailures(item.getResponse());
269+
for (ShardSearchFailure shardFailure : item.getResponse().getShardFailures()) {
270+
assertThat(ExceptionsHelper.unwrap(shardFailure.getCause(), TaskCancelledException.class), notNullValue());
271+
}
272+
}
273+
}
274+
}
248275

249276
public static class ScriptedBlockPlugin extends MockScriptPlugin {
250277
static final String SCRIPT_NAME = "search_block";

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
import org.elasticsearch.common.xcontent.XContent;
3535
import org.elasticsearch.common.xcontent.XContentBuilder;
3636
import org.elasticsearch.common.xcontent.XContentParser;
37+
import org.elasticsearch.tasks.CancellableTask;
38+
import org.elasticsearch.tasks.Task;
39+
import org.elasticsearch.tasks.TaskId;
3740

3841
import java.io.ByteArrayOutputStream;
3942
import java.io.IOException;
@@ -43,6 +46,7 @@
4346
import java.util.Locale;
4447
import java.util.Map;
4548
import java.util.Objects;
49+
import java.util.stream.Collectors;
4650

4751
import static org.elasticsearch.action.ValidateActions.addValidationError;
4852
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue;
@@ -328,4 +332,20 @@ public static void writeSearchRequestParams(SearchRequest request, XContentBuild
328332
xContentBuilder.endObject();
329333
}
330334

335+
@Override
336+
public Task createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
337+
return new CancellableTask(id, type, action, "", parentTaskId, headers) {
338+
@Override
339+
public String getDescription() {
340+
return requests.stream()
341+
.map(SearchRequest::buildDescription)
342+
.collect(Collectors.joining(action + "[", ",", "]"));
343+
}
344+
345+
@Override
346+
public boolean shouldCancelChildrenOnCancellation() {
347+
return true;
348+
}
349+
};
350+
}
331351
}

0 commit comments

Comments
 (0)