[ 
https://issues.apache.org/jira/browse/CAMEL-25679?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-25679 started by shashank.
----------------------------------------
> camel-mongodb - the tailable and change streams consumers stop consuming for 
> good (route still started) when the server is unreachable for longer than the 
> server selection timeout
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25679
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25679
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-mongodb
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> The tailable cursor consumer ({{consumerType=tailable}}, the default) and the 
> change streams consumer ({{consumerType=changeStreams}}) read from a cursor 
> on one thread, {{MongoAbstractConsumerThread.run()}}. When reading fails (for 
> example the connection to the server is lost), the loop logs a WARN ("Will 
> try again on next poll"), closes the cursor, waits 
> {{cursorRegenerationDelay}} (1000 ms by default) and opens a new cursor 
> ({{initializeCursor()}}).
> At main cd2ce899764e the new cursor is opened at line 130, after the {{try}} 
> of the loop (101-115). While the server is still unreachable, opening the 
> cursor fails: the driver gives up after its server selection timeout (30 
> seconds by default) with {{MongoTimeoutException: Timed out while waiting for 
> a server}}. The exception leaves {{run()}}, the consumer thread ends, and:
> * the route stays started and the consumer never reads again, also long after 
> the server is back; only a restart of the route helps;
> * the only trace is the uncaught exception printed on stderr by the thread 
> ({{Exception in thread "Camel (camel-1) thread #1 - mongodb://..." 
> com.mongodb.MongoTimeoutException ...}}), not through the logging framework.
> Trigger: default options, a MongoDB server (or replica set) that cannot be 
> reached for longer than about 31 seconds (server selection timeout plus the 
> regeneration delay): a restart, a failover that takes long, a network outage, 
> maintenance. A long-running tailing or change stream consumer will see such 
> an outage.
> h3. Reproduction
> New {{MongoDbConsumerCursorRegenerationTest}} with Mockito mocks of the 
> driver objects (no server): the cursor of the start fails its read 
> ({{MongoSocketReadException}}), the first new cursor cannot be opened 
> ({{MongoTimeoutException}}), the next one returns a document. On main:
> * tailable consumer: {{mock://result Received message count. Expected: <1> 
> but was: <0>}}, and the test output shows {{Exception in thread "Camel 
> (camel-1) thread #1 - mongodb://myDb" com.mongodb.MongoTimeoutException: 
> Timed out while waiting for a server}};
> * change streams consumer: the same.
> * A third test (the tailing thread run directly, stopped while it opens a new 
> cursor) pins a related small leak of the same lines: a cursor opened while 
> the consumer is being stopped was neither read nor closed on main ({{Wanted 
> but not invoked: mongoCursor.close()}}).
> h3. Proposed fix
> Open the new cursor at the start of the next iteration of the loop, inside 
> its {{try}}: a failure is logged like a failed read ("Exception from 
> consuming from MongoDB caused by ... Will try again on next poll.") and tried 
> again after {{cursorRegenerationDelay}}, until the server is back or the 
> consumer is stopped. A cursor opened while the consumer was being stopped is 
> closed instead of read (stop() could not close it). The {{cursor}} field 
> becomes volatile, as {{stop()}} reads it from another thread.
> While the server is down there is one WARN with stack trace per attempt, 
> every server selection timeout plus {{cursorRegenerationDelay}} (about 31 
> seconds by default), like the WARN that main already logs for every failed 
> read. No option or default changes, so no upgrade guide entry.
> camel-mongodb unit tests with the fix: 21 run, 0 failures, 0 skipped. Not 
> run: the module's integration tests (they need a MongoDB container), a real 
> outage.
> How it was found: reading the consumers' loop during a sweep of reconnect 
> paths; the test confirmed it.
> Not changed: the tailable consumer still ends quietly when the driver throws 
> {{IllegalStateException}} from {{hasNext()}} (meant for a cursor closed by 
> {{stop()}}); the change streams consumer logs a failed read at DEBUG only 
> (CAMEL-16025).
> Affected: main (cd2ce899764e; tested). camel-4.23.x (line 130), camel-4.22.x, 
> camel-4.18.x and camel-4.14.x (line 94) open the new cursor outside the 
> {{try}} the same way (read, not run).
> Duplicate check (2026-10-15): JIRA text "MongoAbstractConsumerThread" 
> (CAMEL-16025, CAMEL-16024, CAMEL-25024, CAMEL-25025, CAMEL-17121 retry logic 
> consolidation; none about the regeneration), "MongoTimeoutException" 
> (CAMEL-24257, camel export; CAMEL-12142, tests), component camel-mongodb with 
> "tailable cursor" (CAMEL-11977 stop on shutdown, 2017); GitHub pull requests 
> "MongoAbstractConsumerThread" (#26961, failure handling of the route, did not 
> touch the regeneration), "mongodb tailable cursor", "mongodb change streams 
> reconnect" (nothing related).
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to