Federico Mariani created CAMEL-24155:
----------------------------------------

             Summary: camel-salesforce - streamQueryResult iterator hangs the 
route thread forever when queryMore fails
                 Key: CAMEL-24155
                 URL: https://issues.apache.org/jira/browse/CAMEL-24155
             Project: Camel
          Issue Type: Bug
          Components: camel-salesforce
            Reporter: Federico Mariani
         Attachments: QueryResultIteratorErrorTest.java

Found during a code review of camel-salesforce on main (4.22.0-SNAPSHOT).

In {{QueryResultIterator.next()}} (internal/processor, lines ~60-94), the 
page-fetch callback passed to {{restClient.queryMore(...)}} completely ignores 
its {{exception}} parameter. On any failure, 
{{AbstractClientBase.doHttpRequest}} invokes the callback with {{response == 
null}} plus a {{SalesforceException}}; {{objectMapper.readValue(null, ...)}} 
then throws inside the Jetty worker thread, so {{latch.countDown()}} — which is 
not in a finally block — is never reached, and {{latch.await()}}, which has *no 
timeout*, blocks the consuming route thread forever. The same hang occurs when 
{{readValue}} throws {{IOException}} or a page unexpectedly contains zero 
records.

*Failure scenario*: {{streamQueryResult=true}} query over a large result set; 
while the route iterates the returned Iterator, the session expires, the 
network blips, or Salesforce returns any non-2xx for the {{nextRecordsUrl}} 
fetch. The route thread blocks permanently inside {{next()}}, the exchange 
never completes, and the only trace is an uncaught-exception log on a Jetty 
worker thread.

*Reproducer*: attached {{QueryResultIteratorErrorTest.java}} (unit test, goes 
under 
{{components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/processor/}}).
 It simulates the asynchronous callback invocation exactly as production does 
(callback fired from a separate thread with a null response and a 
SalesforceException) and fails by preemptive timeout because {{next()}} never 
returns.

*Suggested fix*: in the callback, check {{exception != null}} (and wrap parse 
failures), store the error in a holder, always {{countDown()}} in a finally 
block, and rethrow the stored error from {{next()}} on the iterating thread.

_This issue was researched and filed by Claude Code (AI) on behalf of Federico 
Mariani (fmariani). Full findings document from the review is attached to the 
umbrella issues._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to