You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Andrea Cosentino (Jira)" <ji...@apache.org> on 2026/09/30 09:47:00 UTC

[jira] [Resolved] (CAMEL-25160) camel-mongodb - harden the persistent tail tracking manager

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

Andrea Cosentino resolved CAMEL-25160.
--------------------------------------
    Resolution: Fixed

Fixed via https://github.com/apache/camel/pull/27116 (merged to main as c3632125413b, 4.23.0).

> camel-mongodb - harden the persistent tail tracking manager
> -----------------------------------------------------------
>
>                 Key: CAMEL-25160
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25160
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-mongodb
>            Reporter: Andrea Cosentino
>            Assignee: Andrea Cosentino
>            Priority: Minor
>             Fix For: 4.23.0
>
>
> h3. Summary
> Two small robustness problems in {{MongoDbTailTrackingManager}}, both on the persistent tail tracking
> path ({{persistentTailTracking=true}}).
> h3. The update filter grows, defeating the stated optimisation
> {{initialize()}} deliberately reduces the tracking document to its id:
> {code:java}
> // keep only the _id, the rest is useless and causes more overhead during update
> trackingObj = new Document(MONGO_ID, trackingObj.get(MONGO_ID));
> {code}
> and {{persistToStore()}} immediately undoes it, because it stores the full updated document back:
> {code:java}
> FindOneAndUpdateOptions options = new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER);
> trackingObj = dbCol.findOneAndUpdate(trackingObj, updateObj, options);
> {code}
> From the first persist onwards the filter is {{{_id, <field>: <previous value>}}} rather than
> {{{_id}}}. That is self-consistent for a single writer, but if anything else changes that field - two
> routes configured with the same {{persistentId}}, or an external writer - the update matches nothing,
> {{findOneAndUpdate}} returns {{null}}, and the *next* call passes a null filter.
> That throws from the {{finally}} of {{MongoDbTailingThread.doRun()}}, which lands in the consumer
> thread's catch, regenerates the cursor and persists again: the same non-terminating shape as
> CAMEL-25025.
> h3. recoverFromStore does not guard against a missing document
> {code:java}
> lastVal = dbCol.find(trackingObj).first().get(config.field);
> {code}
> {{first()}} returns {{null}} if the tracking document has gone between {{initialize()}} and this call.
> h3. Proposed fix
> Keep filtering by {{_id}} only, and null-guard the recovery read. Note also that the {{ReentrantLock}} in
> this class guards state that only the single consumer thread touches, so it is redundant rather than
> wrong - worth leaving alone unless it is confusing.
> ----
> _Reported by Claude Code on behalf of oscerd (Andrea Cosentino)._



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