Skip to content

Commit 7ddbda4

Browse files
authored
Check for query cancellation during rewrite (#53166) (#53203)
With ExitableDirectoryReader in place, check for query cancellation during QueryPhase#preProcess where the query rewriting takes place. Follows: #52822 (cherry picked from commit 0d38626)
1 parent c204137 commit 7ddbda4

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

server/src/main/java/org/elasticsearch/search/query/QueryPhase.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,24 @@ public QueryPhase() {
110110

111111
@Override
112112
public void preProcess(SearchContext context) {
113-
context.preProcess(true);
113+
final Runnable cancellation;
114+
if (context.lowLevelCancellation()) {
115+
SearchShardTask task = context.getTask();
116+
cancellation = context.searcher().addQueryCancellation(() -> {
117+
if (task.isCancelled()) {
118+
throw new TaskCancelledException("cancelled");
119+
}
120+
});
121+
} else {
122+
cancellation = null;
123+
}
124+
try {
125+
context.preProcess(true);
126+
} finally {
127+
if (cancellation != null) {
128+
context.searcher().removeQueryCancellation(cancellation);
129+
}
130+
}
114131
}
115132

116133
@Override

server/src/test/java/org/elasticsearch/search/query/QueryPhaseTests.java

+56
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import org.apache.lucene.search.LeafCollector;
5454
import org.apache.lucene.search.MatchAllDocsQuery;
5555
import org.apache.lucene.search.MatchNoDocsQuery;
56+
import org.apache.lucene.search.MultiTermQuery;
57+
import org.apache.lucene.search.PrefixQuery;
5658
import org.apache.lucene.search.Query;
5759
import org.apache.lucene.search.ScoreDoc;
5860
import org.apache.lucene.search.Sort;
@@ -76,6 +78,7 @@
7678
import org.elasticsearch.index.mapper.MapperService;
7779
import org.elasticsearch.index.mapper.NumberFieldMapper;
7880
import org.elasticsearch.index.query.ParsedQuery;
81+
import org.elasticsearch.index.query.QueryShardContext;
7982
import org.elasticsearch.index.search.ESToParentBlockJoinQuery;
8083
import org.elasticsearch.index.shard.IndexShard;
8184
import org.elasticsearch.index.shard.IndexShardTestCase;
@@ -84,6 +87,7 @@
8487
import org.elasticsearch.search.internal.ScrollContext;
8588
import org.elasticsearch.search.internal.SearchContext;
8689
import org.elasticsearch.search.sort.SortAndFormats;
90+
import org.elasticsearch.tasks.TaskCancelledException;
8791
import org.elasticsearch.test.TestSearchContext;
8892

8993
import java.io.IOException;
@@ -834,7 +838,59 @@ public void testMinScore() throws Exception {
834838

835839
reader.close();
836840
dir.close();
841+
}
842+
843+
public void testCancellationDuringPreprocess() throws IOException {
844+
try (Directory dir = newDirectory();
845+
RandomIndexWriter w = new RandomIndexWriter(random(), dir, newIndexWriterConfig())) {
846+
847+
for (int i = 0; i < 10; i++) {
848+
Document doc = new Document();
849+
StringBuilder sb = new StringBuilder();
850+
for (int j = 0; j < i; j++) {
851+
sb.append('a');
852+
}
853+
doc.add(new StringField("foo", sb.toString(), Store.NO));
854+
w.addDocument(doc);
855+
}
856+
w.flush();
857+
w.close();
858+
859+
try (IndexReader reader = DirectoryReader.open(dir)) {
860+
TestSearchContext context = new TestSearchContextWithRewriteAndCancellation(
861+
null, indexShard, newContextSearcher(reader));
862+
PrefixQuery prefixQuery = new PrefixQuery(new Term("foo", "a"));
863+
prefixQuery.setRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_REWRITE);
864+
context.parsedQuery(new ParsedQuery(prefixQuery));
865+
SearchShardTask task = mock(SearchShardTask.class);
866+
when(task.isCancelled()).thenReturn(true);
867+
context.setTask(task);
868+
expectThrows(TaskCancelledException.class, () -> new QueryPhase().preProcess(context));
869+
}
870+
}
871+
}
872+
873+
private static class TestSearchContextWithRewriteAndCancellation extends TestSearchContext {
837874

875+
private TestSearchContextWithRewriteAndCancellation(QueryShardContext queryShardContext,
876+
IndexShard indexShard,
877+
ContextIndexSearcher searcher) {
878+
super(queryShardContext, indexShard, searcher);
879+
}
880+
881+
@Override
882+
public void preProcess(boolean rewrite) {
883+
try {
884+
searcher().rewrite(query());
885+
} catch (IOException e) {
886+
fail("IOException shouldn't be thrown");
887+
}
888+
}
889+
890+
@Override
891+
public boolean lowLevelCancellation() {
892+
return true;
893+
}
838894
}
839895

840896
private static ContextIndexSearcher newContextSearcher(IndexReader reader) throws IOException {

0 commit comments

Comments
 (0)