[
https://issues.apache.org/jira/browse/CAMEL-25506?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Work on CAMEL-25506 started by shashank.
----------------------------------------
> camel-lucene - concurrent queries can get another query's hits, and queries
> fail after the route is restarted
> -------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25506
> URL: https://issues.apache.org/jira/browse/CAMEL-25506
> Project: Camel
> Issue Type: Bug
> Components: camel-lucene
> Reporter: shashank
> Assignee: shashank
> Priority: Major
>
> {{LuceneQueryProducer}} creates one {{LuceneSearcher}} in {{doStart()}} and
> uses it for every exchange (Camel producers are shared by concurrent
> exchanges). {{LuceneSearcher}} keeps the state of a query in fields (main
> c578a42a776d): {{open()}} assigns {{indexReader}} and {{indexSearcher}}
> (lines 47-51) and {{doSearch()}} assigns {{hits}} (line 94), which
> {{search()}} then iterates (line 71). So:
> * two exchanges querying at the same time can get each other's results: one
> exchange assigns {{hits}} between the other's search and its loop over
> {{hits}}. In the test below, 27 to 48 of 20000 queries (8 threads, two terms)
> returned the hits of the other term on main;
> * every query opens a new {{DirectoryReader}} and only the one in the field
> when the producer stops is closed; the others are left to the garbage
> collector;
> * {{LuceneQueryProducer.doStop()}} calls {{LuceneSearcher.close()}}, which
> closes the endpoint's {{Analyzer}} (the configured bean or the endpoint's
> default). After the route is stopped and started again, every query fails
> with {{org.apache.lucene.store.AlreadyClosedException: this Analyzer is
> closed}} until the CamelContext is restarted; when the route had not run a
> query yet, the stop fails with a {{NullPointerException}} ({{indexReader}} is
> null), logged as a WARN by the shutdown strategy.
> {{LuceneQueryProcessor}} has the same reader handling (a new searcher in a
> shared field per exchange, never closed).
> h3. Reproduction
> New {{LuceneQueryProducerLifecycleTest}} (an index of 20 "alpha" and 20
> "beta" documents built in {{@BeforeEach}}, a route {{direct:query}} to
> {{lucene:queryIndex:query}}):
> * {{queryWorksAfterRouteRestart}} (deterministic): on main {{a query after
> the route was restarted must succeed ==> expected: <null> but was:
> <org.apache.lucene.store.AlreadyClosedException: this Analyzer is closed>}}.
> * {{concurrentQueriesGetTheirOwnHits}} (20000 queries on 8 threads, about 2
> s; it cannot force the interleaving, it makes it very likely): on main {{each
> query must get the hits of its own query, but 39 of 20000 did not, e.g.
> [alpha: got hit 'beta document 0', ...]}}; it failed in all six runs on main
> (27 to 48 wrong answers) and passed in every run with the fix.
> h3. Proposed fix
> Each exchange uses its own {{LuceneSearcher}} ({{open}}, {{search}},
> {{close}} in a {{finally}}); the producer no longer keeps one, so
> {{doStart}}/{{doStop}} are gone. {{LuceneSearcher.close()}} closes only its
> reader (null-safe), not the analyzer, which belongs to the endpoint or the
> registry. {{LuceneQueryProcessor}} does the same (no dedicated test;
> {{LuceneQueryProcessorIT}} passes). Code that calls {{LuceneSearcher}}
> directly now has to close its analyzer itself. The {{Hits}} hold the stored
> values (and the {{Document}} when requested), so closing the reader after
> building them is safe; the existing ITs still pass. camel-lucene tests with
> the fix: {{LuceneQueryProducerLifecycleTest}} 2,
> {{LuceneIndexAndQueryProducerIT}} 4, {{LuceneQueryProcessorIT}} 2, 0 failures.
> Found with a TLA+ model of the producer and searcher (one action per field
> read/write: open reader, create searcher, collect hits, iterate hits; route
> stop/start): "every answer holds the hits of its own query" is violated in 7
> steps with two threads, "no reader is left open after the stop" in 12 steps
> with one thread and two queries, and "no query runs on a closed analyzer" in
> 9 steps (query, stop, start, query). With the fix all properties hold for 2
> and 3 threads and a restart. Then confirmed with the real component as above.
> Affected: main, camel-4.22.x, camel-4.18.x, camel-4.14.x (same code, GitHub
> contents API; unchanged since 2.x).
> Duplicate check (2026-10-09): JIRA component camel-lucene (8 issues, all
> upgrades or naming), text "LuceneSearcher" (4, upgrades), "this Analyzer is
> closed" (none); GitHub pull requests "camel-lucene": none about the producers.
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)