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

Work on CAMEL-25607 started by shashank.
----------------------------------------
> camel-mongodb-gridfs - with the default TimeStamp query strategy (and 
> PersistentTimestamp) the consumer routes every file uploaded since it started 
> again at each poll, every 500 ms
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25607
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25607
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-mongodb-gridfs
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> {{GridFsConsumer}} with a timestamp query strategy 
> ({{queryStrategy=TimeStamp}}, the default, and {{PersistentTimestamp}}) asks 
> for the files whose {{uploadDate}} is greater than the date of the newest 
> file it has routed. Since CAMEL-17121 (3.13, the loop was replaced by a 
> repeated task) that date is lost between the polls ({{GridFsConsumer}} at 
> main a7169d7c6ab6):
> {code:java}
> // run(), lines 128-133: the start date is captured once
> Date finalFromDate = fromDate;
> task.run(endpoint.getCamelContext(),
>         () -> processCollection(finalFromDate, usesTimestamp, 
> persistsTimestamp, usesAttribute, finalPtsCollection,
>                 finalPersistentTimestamp));
> // processCollection(Date fromDate, ...), lines 180-183: moves the parameter 
> of this call only
> if (usesTimestamp && file.getUploadDate().compareTo(fromDate) > 0) {
>     fromDate = file.getUploadDate();
>     dateModified = true;
> }
> {code}
> Every poll therefore queries {{uploadDate > <date the consumer started>}} 
> again. A file uploaded after the consumer started is routed by the first poll 
> that sees it and then again by every following poll, every {{delay}} (500 ms 
> by default), for as long as the route runs. Before CAMEL-17121 {{fromDate}} 
> was a local variable of the loop and the file was routed once.
> Configuration: the defaults. {{from("mongodb-gridfs:myDb?database=test")}} 
> and one file created in the bucket are enough; the route receives that file 
> about twice per second.
> With {{PersistentTimestamp}} the effect is the same until the route is 
> restarted (the stored timestamp is written again at every poll, with the same 
> value; a restart then reads it and starts after the file). The strategies 
> that use the file attribute ({{FileAttribute}}, 
> {{TimeStampAndFileAttribute}}, {{PersistentTimestampAndFileAttribute}}) are 
> not affected: their query also asks for files without the attribute.
> The integration test of the module ({{GridFsConsumerIT}}) does not see it: 
> all files have the same body, and the mock endpoint is asserted as soon as 
> the expected number of messages has arrived, so a file that is routed again a 
> poll later is either not seen or looks like the next expected message. 
> CAMEL-24905 (flaky {{GridFsConsumerIT.testAttribute}}, "Expected: <1> but 
> was: <2>") is possibly related, not reproduced: the test that failed there 
> uses the {{FileAttribute}} strategy, which is not affected, and the root 
> causes found in that ticket were the shared mock endpoint and buckets that 
> were not cleaned between the tests.
> h3. Reproduction
> New {{GridFsConsumerTimestampTest}} (3 tests, no MongoDB needed): the real 
> {{GridFsConsumer}} polls a fake bucket (Mockito) that answers the 
> {{uploadDate > date}} query of each poll from a list of files, the way the 
> server does. All three fail with the consumer of main:
> * {{timestampStrategyRoutesAFileOnce}}: {{three polls saw the file, it must 
> be routed by the first of them only ==> expected: <[first]> but was: <[first, 
> first, first, first]>}} (three or four times, depending on the poll that is 
> running when the test asserts)
> * {{timestampStrategyRoutesALaterFileOnce}}: {{expected: <[first, second]> 
> but was: <[first, first, first, first, second, first, second, first, 
> second]>}}
> * {{persistentTimestampStrategyRoutesAFileOnce}}: {{expected: <[first]> but 
> was: <[first, first, first]>}}
> h3. Proposed fix
> Keep the date in a field of the consumer, so that a poll starts from the date 
> the previous poll reached. The field is {{volatile}}: {{run()}} sets the 
> start value on the thread of the consumer's {{executor}} before it schedules 
> the polls, and the polls read and move it on the thread of the 
> {{taskExecutor}}. Nothing else changes.
> A stop and start of the consumer is as before: {{doStart}} runs {{run()}} 
> again, which sets the date to "now" for {{TimeStamp}} and reads the stored 
> timestamp for {{PersistentTimestamp}}.
> Behaviour change, with a 4.24 upgrade-guide entry: a file is routed once.
> Not changed, seen in the same method: a failed exchange still moves the 
> timestamp (and sets the file attribute to {{done}}), an exception thrown by 
> {{process}} is still swallowed, and an exception of the poll itself (MongoDB 
> not reachable) still ends the repeated task. These were the same before 
> CAMEL-17121 or are a different defect, and would be separate tickets.
> camel-mongodb-gridfs tests with the fix: 3 run, 0 failures (the module has no 
> other unit test) (the integration tests need a MongoDB container and were not 
> run).
> How it was found: a small TLA+ model of the polls (upload, query, route, end 
> of poll). For the code of main TLC reports a violation of "a file is routed 
> at most once" after two polls (7 states) and of "the timestamp is stored only 
> when it moved"; with the date kept between the polls both hold, and no file 
> is skipped. The model is a sketch of the code; the evidence is the test above.
> Affected: main (a7169d7c6ab6, tested). Read, not run: camel-4.23.x 
> (197e70656a41), camel-4.22.x (8dfae2fa437c), camel-4.18.x (c3fd5317a5a0), 
> camel-4.14.x, camel-3.14.x and the camel-3.13.0 tag have the same lines 
> ({{finalFromDate}} captured by the task, {{processCollection(Date fromDate, 
> ...)}}), so every release since 3.13.0. The camel-3.12.0 tag still has the 
> loop with a local variable.
> Duplicate check (2026-10-13): JIRA text "GridFsConsumer" (3: CAMEL-24286, 
> CAMEL-24272, CAMEL-17121, none about duplicates), "gridfs consumer" (3), 
> "gridfs duplicate" (2), "gridfs timestamp" (1), "mongodb-gridfs" (26, none 
> about the consumer routing a file more than once); GitHub pull requests 
> "gridfs": only #26787 (CAMEL-24905, test only) touches the consumer tests.
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to