From 030095cd81419bbdf338c82523e66f220aeefc3e Mon Sep 17 00:00:00 2001 From: cyforkk <1139009771@qq.com> Date: Wed, 29 Jul 2026 22:15:46 +0800 Subject: [PATCH] feat: Add Executor support to Monitor for concurrent search (issue #16198) Allow users to pass an Executor to MonitorConfiguration for inter-segment concurrency in search operations. When set, the Monitor will use this Executor when creating IndexSearcher instances. Changes: - Add Executor field to MonitorConfiguration with getter/setter - Store Executor in Monitor constructor - Use Executor when creating IndexSearcher in match() and debug() methods Co-Authored-By: Claude --- .../org/apache/lucene/monitor/Monitor.java | 11 +++++++-- .../lucene/monitor/MonitorConfiguration.java | 23 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lucene/monitor/src/java/org/apache/lucene/monitor/Monitor.java b/lucene/monitor/src/java/org/apache/lucene/monitor/Monitor.java index ac0600870f9e..666577d15f1b 100644 --- a/lucene/monitor/src/java/org/apache/lucene/monitor/Monitor.java +++ b/lucene/monitor/src/java/org/apache/lucene/monitor/Monitor.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.Executor; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.LeafReader; @@ -48,6 +49,8 @@ public class Monitor implements Closeable { private final long commitBatchSize; + private final Executor executor; + /** * Create a non-persistent Monitor instance with the default term-filtering Presearcher * @@ -96,6 +99,7 @@ public Monitor(Analyzer analyzer, Presearcher presearcher, MonitorConfiguration } this.commitBatchSize = configuration.getQueryUpdateBufferSize(); + this.executor = configuration.getExecutor(); } /** @@ -219,7 +223,9 @@ public MultiMatchingQueries match( Document[] docs, MatcherFactory factory) throws IOException { try (DocumentBatch batch = DocumentBatch.of(analyzer, docs)) { LeafReader reader = batch.get(); - CandidateMatcher matcher = factory.createMatcher(new IndexSearcher(batch.get())); + IndexSearcher indexSearcher = + (executor != null) ? new IndexSearcher(reader, executor) : new IndexSearcher(reader); + CandidateMatcher matcher = factory.createMatcher(indexSearcher); StandardQueryCollector collector = new StandardQueryCollector<>(matcher); long buildTime = queryIndex.search(t -> presearcher.buildQuery(reader, t), collector); return matcher.finish(buildTime, collector.queryCount); @@ -318,7 +324,8 @@ public PresearcherMatches debug( Document[] docs, MatcherFactory factory) throws IOException { try (DocumentBatch batch = DocumentBatch.of(analyzer, docs)) { LeafReader reader = batch.get(); - IndexSearcher searcher = new IndexSearcher(reader); + IndexSearcher searcher = + (executor != null) ? new IndexSearcher(reader, executor) : new IndexSearcher(reader); searcher.setQueryCache(null); PresearcherQueryCollector collector = new PresearcherQueryCollector<>(factory.createMatcher(searcher)); diff --git a/lucene/monitor/src/java/org/apache/lucene/monitor/MonitorConfiguration.java b/lucene/monitor/src/java/org/apache/lucene/monitor/MonitorConfiguration.java index 03aa1736c8bf..a169e69b6d6b 100644 --- a/lucene/monitor/src/java/org/apache/lucene/monitor/MonitorConfiguration.java +++ b/lucene/monitor/src/java/org/apache/lucene/monitor/MonitorConfiguration.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import org.apache.lucene.analysis.core.KeywordAnalyzer; import org.apache.lucene.index.IndexWriter; @@ -39,6 +40,7 @@ public class MonitorConfiguration { private MonitorQuerySerializer serializer; private boolean readOnly = false; private IOSupplier directoryProvider = () -> new ByteBuffersDirectory(); + private Executor executor = null; private static IndexWriterConfig defaultIndexWriterConfig() { IndexWriterConfig iwc = new IndexWriterConfig(new KeywordAnalyzer()); @@ -165,4 +167,25 @@ public MonitorConfiguration setQueryUpdateBufferSize(int size) { public int getQueryUpdateBufferSize() { return queryUpdateBufferSize; } + + /** + * Set the Executor to use for concurrent search. + * + *

If set, the Monitor will pass this Executor to the IndexSearcher it creates internally, + * allowing for inter-segment concurrency in search operations. + * + * @param executor the Executor to use for concurrent search + * @return the current configuration + */ + public MonitorConfiguration setExecutor(Executor executor) { + this.executor = executor; + return this; + } + + /** + * @return the Executor used for concurrent search, or null if not set + */ + public Executor getExecutor() { + return executor; + } }