oscerd opened a new pull request, #27116:
URL: https://github.com/apache/camel/pull/27116
Two defects from a second pass over `camel-mongodb`, a commit each.
## CAMEL-25159 — `findAll`, `distinct` and `aggregate` ran their query twice
All three had this shape:
```java
try {
ret.iterator().forEachRemaining(result::add);
exchange.getMessage().setHeader(RESULT_PAGE_SIZE, result.size());
} finally {
ret.iterator().close();
}
```
`MongoIterable.iterator()` is not an accessor for an already-open cursor —
it **executes**. From
`mongodb-driver-sync` 5.9.2:
```java
public MongoCursor<T> iterator() {
return new MongoBatchCursorAdapter<>(execute());
}
```
So the `finally` opened a *second* cursor — another round trip, and for
`aggregate` a second run of the
whole pipeline — closed that one, and left the cursor that had actually been
read unclosed. If
`forEachRemaining` threw part-way, that first cursor leaked outright.
Now a held cursor in try-with-resources: the query runs once, and the cursor
that is read is the one that
is closed. Affects `findAll` and `aggregate` whenever `outputType` is not
`MongoIterable`, and `distinct`
always.
## CAMEL-25160 — the tail tracker undid its own optimisation, and could wedge
`initialize()` reduces the tracking document to its id on purpose:
```java
// keep only the _id, the rest is useless and causes more overhead during
update
trackingObj = new Document(MONGO_ID, trackingObj.get(MONGO_ID));
```
and `persistToStore()` immediately undid it by storing the full
`findOneAndUpdate(..., AFTER)` result
back. From the first persist onwards the filter also matched on the previous
value. That is
self-consistent for a single writer, but anything else touching the field —
two routes sharing a
`persistentId` — leaves the update matching nothing, `trackingObj` null, and
the *next* persist throwing
from the `finally` of `doRun()`, which lands in the consumer thread's catch,
regenerates the cursor and
persists again. That is the non-terminating shape of CAMEL-25025, which is
why the issues are linked.
Filter on the id only, and null-guard the recovery read, which previously
dereferenced `first()`
unguarded.
## Tests
`MongoDbProducerCursorTest` drives all three operations through a mocked
`MongoClient` chain and asserts
`verify(iterable, times(1)).iterator()`. The endpoint starts as long as
`mongoConnection` is supplied, so
no server is needed.
Revert-checked one site at a time: restoring the old `finally` on `distinct`
alone fails exactly
`testDistinctOpensOneCursor` with *wanted 1 time but was 2 times*, while the
other two keep passing.
**This adds `mockito-core` in test scope**, which is the one thing here
worth a second opinion. A call
count is the only way to prove this fix, the module had no mocking library,
and mockito-core is already
the convention in sibling components (`camel-pulsar`,
`camel-debezium-common`). If you would rather not
take the dependency, the fix stands on the driver evidence and the existing
ITs cover the functional
path — say so and I will drop the test rather than argue for it.
No upgrade-guide entry: neither change alters a user-visible contract, just
one fewer round trip and
tail-tracking persistence that behaves identically for the single-writer
case it was already restricted
to.
Module suite green (18 tests); full reactor `mvn clean install -DskipTests
-DskipITs` green with no
generated drift.
_Claude Code on behalf of oscerd_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]