Skip to content

Commit 0d38626

Browse files
authored
Check for query cancellation during rewrite (#53166)
With ExitableDirectoryReader in place, check for query cancellation during QueryPhase#preProcess where the query rewriting takes place. Follows: #52822
1 parent 8f17b21 commit 0d38626

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-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

+52
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;
@@ -75,6 +77,7 @@
7577
import org.elasticsearch.index.mapper.MapperService;
7678
import org.elasticsearch.index.mapper.NumberFieldMapper;
7779
import org.elasticsearch.index.query.ParsedQuery;
80+
import org.elasticsearch.index.query.QueryShardContext;
7881
import org.elasticsearch.index.search.ESToParentBlockJoinQuery;
7982
import org.elasticsearch.index.shard.IndexShard;
8083
import org.elasticsearch.index.shard.IndexShardTestCase;
@@ -83,6 +86,7 @@
8386
import org.elasticsearch.search.internal.ScrollContext;
8487
import org.elasticsearch.search.internal.SearchContext;
8588
import org.elasticsearch.search.sort.SortAndFormats;
89+
import org.elasticsearch.tasks.TaskCancelledException;
8690
import org.elasticsearch.test.TestSearchContext;
8791

8892
import java.io.IOException;
@@ -825,7 +829,55 @@ public void testMinScore() throws Exception {
825829

826830
reader.close();
827831
dir.close();
832+
}
833+
834+
public void testCancellationDuringPreprocess() throws IOException {
835+
try (Directory dir = newDirectory();
836+
RandomIndexWriter w = new RandomIndexWriter(random(), dir, newIndexWriterConfig())) {
837+
838+
for (int i = 0; i < 10; i++) {
839+
Document doc = new Document();
840+
doc.add(new StringField("foo", "a".repeat(i), Store.NO));
841+
w.addDocument(doc);
842+
}
843+
w.flush();
844+
w.close();
845+
846+
try (IndexReader reader = DirectoryReader.open(dir)) {
847+
TestSearchContext context = new TestSearchContextWithRewriteAndCancellation(
848+
null, indexShard, newContextSearcher(reader));
849+
PrefixQuery prefixQuery = new PrefixQuery(new Term("foo", "a"));
850+
prefixQuery.setRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_REWRITE);
851+
context.parsedQuery(new ParsedQuery(prefixQuery));
852+
SearchShardTask task = mock(SearchShardTask.class);
853+
when(task.isCancelled()).thenReturn(true);
854+
context.setTask(task);
855+
expectThrows(TaskCancelledException.class, () -> new QueryPhase().preProcess(context));
856+
}
857+
}
858+
}
859+
860+
private static class TestSearchContextWithRewriteAndCancellation extends TestSearchContext {
828861

862+
private TestSearchContextWithRewriteAndCancellation(QueryShardContext queryShardContext,
863+
IndexShard indexShard,
864+
ContextIndexSearcher searcher) {
865+
super(queryShardContext, indexShard, searcher);
866+
}
867+
868+
@Override
869+
public void preProcess(boolean rewrite) {
870+
try {
871+
searcher().rewrite(query());
872+
} catch (IOException e) {
873+
fail("IOException shouldn't be thrown");
874+
}
875+
}
876+
877+
@Override
878+
public boolean lowLevelCancellation() {
879+
return true;
880+
}
829881
}
830882

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

0 commit comments

Comments
 (0)