[
https://issues.apache.org/jira/browse/SOLR-18348?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
ASF GitHub Bot updated SOLR-18348:
----------------------------------
Labels: pull-request-available (was: )
> `buildOnCommit=true` suggester rebuild blocks commit (and the client request)
> indefinitely with no timeout
> ----------------------------------------------------------------------------------------------------------
>
> Key: SOLR-18348
> URL: https://issues.apache.org/jira/browse/SOLR-18348
> Project: Solr
> Issue Type: Bug
> Components: Suggester
> Affects Versions: 9.10.1
> Reporter: Eric Pugh
> Assignee: Eric Pugh
> Priority: Major
> Labels: pull-request-available
> Time Spent: 10m
> Remaining Estimate: 0h
>
> h3. Problem
> When a suggester is configured with `buildOnCommit=true`, a slow suggester
> rebuild does not just make that commit take longer in the background — it
> synchronously blocks the commit call itself, and therefore the client/update
> request waiting on it, with *no timeout*. Under sustained heavy indexing
> combined with throttled storage (e.g. an Azure disk after burst credits are
> exhausted), this manifests as outright request timeouts requiring manual
> operator intervention, rather than graceful degradation.
> A customer hit this in production: ~4 million product documents being indexed
> against a suggester with an I/O-intensive `AnalyzingInfixSuggester`
> configuration, on a disk that had exhausted its burst-credit allowance.
> Indexing requests began timing out. Thread dumps showed threads stuck in:
> {code}
> "searcherExecutor-250-thread-3-processing-...-core_node4" ... RUNNABLE
> at org.apache.lucene.util.compress.LZ4.decompress(LZ4.java:138)
> at
> org.apache.lucene.codecs.lucene90.LZ4WithPresetDictCompressionMode$LZ4WithPresetDictDecompressor.decompress(...)
> at
> org.apache.lucene.codecs.lucene90.compressing.Lucene90CompressingStoredFieldsReader...
> at
> org.apache.lucene.search.suggest.DocumentDictionary$DocumentInputIterator.next(DocumentDictionary.java:169)
> at
> org.apache.lucene.search.suggest.analyzing.AnalyzingInfixSuggester.build(AnalyzingInfixSuggester.java:346)
> {code}
> h3. Root cause
> * \{{SuggestComponent.SuggesterListener.newSearcher()}} calls
> \{{suggester.build(core, newSearcher)}} synchronously — see
> [SuggestComponent.java|https://github.com/apache/solr/blob/releases/solr/9.10.1/solr/core/src/java/org/apache/solr/handler/component/SuggestComponent.java#L566-L571].
> * This listener is invoked as a \{{newSearcherListener}} on \{{SolrCore}}'s
> \{{searcherExecutor}}, which is explicitly a *single-threaded* executor (see
> the comment "WARNING: this code assumes a single threaded executor" in
> \{{SolrCore.java}}). Warmup, all \{{newSearcherListener}}s, and searcher
> registration all run sequentially on this one thread.
> * \{{DirectUpdateHandler2.commit()}} blocks the committing thread on
> \{{waitSearcher[0].get()}} — a no-arg, *no-timeout* \{{Future.get()}} —
> whenever \{{waitSearcher=true}}, which is the default for a normal
> \{{commit=true}} request (\{{CommitUpdateCommand.waitSearcher}} defaults to
> \{{true}}).
> * Net effect: an arbitrarily slow \{{buildOnCommit}} rebuild (or any other
> slow \{{newSearcherListener}}) blocks the commit-issuing thread/HTTP request
> indefinitely, bounded only by client/proxy socket timeouts.
> This exact hazard is already flagged in the reference guide ("Some lookup
> implementations may take a long time to build... using buildOnCommit or
> buildOnOptimize, particularly with a high frequency of soft commits is not
> recommended") but the current behavior is worse than "slow" — it can hang a
> commit indefinitely with no internal safeguard.
> Note: \{{SpellCheckComponent}} has an analogous
> \{{buildOnCommit}}/\{{SpellCheckerListener}} pattern and likely shares this
> same architectural risk; filing this ticket scoped to \{{SuggestComponent}}
> only.
> h3. Reproduction
> Two JUnit tests demonstrate this deterministically using a test-only
> dictionary that simulates slow I/O (sleeping a fixed time per term, so total
> build time is bounded and reproducible):
> * \{{SuggestComponentBuildOnCommitBlocksCommitTest}} — with
> \{{buildOnCommit=true}}, \{{commit()}} takes as long as the (artificially
> slow) suggester build.
> * \{{SuggestComponentBuildOnCommitDisabledCommitStaysFastTest}} — same slow
> dictionary, \{{buildOnCommit=false}}: \{{commit()}} stays fast, isolating the
> cause to \{{buildOnCommit}} itself.
> h3. Suggested direction (open to discussion)
> * Run \{{buildOnCommit}}/\{{buildOnOptimize}} suggester rebuilds off the
> shared single-threaded \{{searcherExecutor}} (e.g. a dedicated executor) so
> they don't block warmup/registration/commit for other listeners.
> * And/or decouple the rebuild from the commit's \{{waitSearcher}} path
> entirely, so a slow rebuild degrades to "suggestions are stale a bit longer"
> rather than "commit hangs."
> * And/or add an explicit, documented timeout/async option for
> \{{buildOnCommit}}.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]