shashank created CAMEL-25711:
--------------------------------

             Summary: camel-mongodb-gridfs - the consumer stops polling for 
good, without a log line and with the route still started, after one poll fails 
(for example MongoDB not reachable for longer than the server selection timeout)
                 Key: CAMEL-25711
                 URL: https://issues.apache.org/jira/browse/CAMEL-25711
             Project: Camel
          Issue Type: Bug
          Components: camel-mongodb-gridfs
            Reporter: shashank
            Assignee: shashank


{{GridFsConsumer}} polls with a {{BackgroundTask}} built 
{{withUnlimitedDuration()}} ({{GridFsConsumer.run}}, main 18f53efde6c7 
{{GridFsConsumer.java}} 124-139). Only {{getProcessor().process(exchange)}} is 
inside a {{try}} in {{processCollection}}; the query of the bucket 
({{getGridFSFileMongoCursor}}, 151), {{cursor.hasNext()}} / {{next()}}, the 
{{findOneAndUpdate}} that marks a file {{processing}} for the file attribute 
strategies (162), {{openDownloadStream}} (166) and the update of the persistent 
timestamp (202) are not. When one of them throws, for example a 
{{MongoTimeoutException}} because MongoDB cannot be reached for longer than the 
server selection timeout (30 s by default) or a {{MongoSocketReadException}} 
when the connection drops while the cursor reads, the exception leaves the 
supplier. {{BackgroundTask.runTaskWrapper}} marks the task failed, releases 
{{run()}} (CAMEL-24286) and rethrows on the scheduler thread, so 
{{scheduleWithFixedDelay}} never runs the task again.

The consumer then stays started and routes nothing until the route is 
restarted. Nothing is logged: the exception ends in the {{Future}} of the 
scheduled task. This happens with every query strategy, with the default 
options.

With {{queryStrategy=PersistentTimestamp}} or 
{{PersistentTimestampAndFileAttribute}} there is a second path: {{run()}} reads 
the persistent timestamp collection (105-119) on the consumer's executor thread 
before it schedules the polls. If MongoDB cannot be reached when the route 
starts, {{run()}} throws and no poll is ever scheduled.

h3. Reproduction

Two new tests in {{GridFsConsumerTimestampTest}} use the fake bucket of that 
class (Mockito, no MongoDB):
* {{consumerKeepsPollingAfterAFailedPoll}}, once for each of the 5 query 
strategies: the first 2 queries of the bucket throw {{MongoTimeoutException}}, 
then a file is stored. On main the consumer never polls again ({{the consumer 
did not poll 3 times}}) and the file is never routed.
* 
{{persistentTimestampStrategyKeepsPollingWhenTheTimestampCannotBeReadAtStart}}: 
the first read of the timestamp collection throws. On main no poll runs.

On main all 6 cases fail; with the fix they pass.

h3. Proposed fix

The supplier of the task calls a new {{poll}} method that catches the 
exception, reports the first failure of a run of failures through the 
consumer's {{ExceptionHandler}} (WARN with the stack trace by default; the next 
ones at DEBUG, as the polls run every {{delay}}, 500 ms by default; one INFO 
line when a poll works again), and returns {{false}}. The next poll then tries 
again after {{delay}}. {{camel-mongodb}} also catches the exception of a poll 
and goes on in its consumer thread ({{MongoAbstractConsumerThread.java}} 
103-110 on main, CAMEL-16025); it logs every failure at WARN with the stack 
trace, this change reports only the first of a run of failures because the 
polls repeat every {{delay}}. The persistent timestamp is read by the first 
poll that can reach MongoDB instead of by {{run()}}, so a failure there is 
retried in the same way. No option or default changes.

Not changed: a file claimed with the {{processing}} attribute (file attribute 
strategies) before the poll fails still keeps that attribute, as before.

How it was found: CAMEL-24286 names this path in its description, but its fix 
changed only {{BackgroundTask}}, and {{run()}} now returns while the poller 
stays dead. The camel-mongodb consumer had the same "consumer thread ends on a 
server outage" defect (CAMEL-25679). The tests confirmed it.

Affected: main (18f53efde6c7; tested). camel-4.23.x and camel-4.22.x poll with 
the same {{BackgroundTask}} and have the same uncaught calls and the same 
timestamp read in {{run()}} (read, not run). camel-4.18.x and camel-4.14.x have 
the same uncaught calls, but {{run()}} polls with a {{ForegroundTask}} there: 
the exception leaves {{run()}} and ends the consumer thread, with the same 
result (only the default handler of the thread prints it on stderr) (read, not 
run).

Duplicate check (2026-10-16): JIRA text "gridfs consumer", "GridFsConsumer", 
"gridfs polling stops" (CAMEL-25607, CAMEL-24905, CAMEL-24272, CAMEL-24286, 
CAMEL-23577, CAMEL-17121: CAMEL-24286 describes the path but fixed only 
BackgroundTask; none about the consumer staying stopped); GitHub pull requests 
"gridfs", "GridFsConsumer" (#27794, #26787, #25217, #25164: none about this).

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to