davsclaus opened a new pull request, #26848: URL: https://github.com/apache/camel/pull/26848
_Claude Code on behalf of Claus Ibsen (davsclaus)_ JIRA: https://issues.apache.org/jira/browse/CAMEL-24993 A deep review of the dynamic routing EIPs (toD / `SendDynamicProcessor`, Routing Slip, Dynamic Router) and the producer cache they share found the bugs below. Each fix has a test that fails without it. 1. **toD sent the exchange after its pre-processor failed.** When the pre-processor of a `SendDynamicAware` component (the optimised toD used by components such as http or kafka) threw an exception, `SendDynamicProcessor` set the exception and called the callback, but did not return. It then still sent the exchange to the endpoint, and the callback ran a second time when the send completed. Now it returns after the failure, and it also stops a prototype endpoint that is then not used. 2. **A routing slip did not stop a prototype endpoint whose step completed asynchronously.** With `cacheSize=-1`, each recipient is a prototype endpoint that should be stopped after use. That only happened when the step completed synchronously. When the first step completed asynchronously, its endpoint was never stopped; later steps were already handled. This also applies to the Dynamic Router, which extends the Routing Slip. 3. **After purging a producer cache, the next send to the last-used endpoint used a stopped producer.** `DefaultProducerCache.purge()` (the JMX `purge` operation of a producer cache) stops and restarts the producer pool, but kept its reference to the last-used producer. The next send to that endpoint took the fast path and reused the stopped producer. `doStop()` already clears this reference, and `purge()` now does too. ### Not changed (left for follow-up) - **No extended statistics on the fast path.** `DefaultProducerCache.acquireProducer` does not record a hit in the extended endpoint utilization statistics when it reuses the last-used producer, so those JMX statistics undercount for singleton producers. - **Producer not released if the callback throws.** `DefaultProducerCache.doInAsyncProducer` does not release the producer when the producer callback itself throws. None of the EIPs reviewed here throw from their callbacks. - **Hidden exception in `SendDynamicProcessor.doInit`.** When the `SendDynamicAware` fallback lookup finds nothing, it throws a `NullPointerException` that is caught and ignored. The behaviour is still correct, since no dynamic aware is used. No outside PRs overlap with this area. ### Tests - New `ToDynamicSendDynamicAwarePreProcessorFailureTest` (with a test `KaboomSendDynamicAware` whose pre-processor fails), `RoutingSlipPrototypeAsyncTest` and `DefaultProducerCachePurgeTest`. Each fails without its fix and passes with it. - All 124 `*ToDynamic*`, `*RoutingSlip*`, `*DynamicRouter*`, `*ProducerCache*` and `*SendDynamic*` tests pass on the rebased branch. - The full `core/camel-support` (125 tests) and `core/camel-core` suites pass: 7563 tests, 0 failures, 44 skipped. `FileConsumerIdempotentKeyNameAndSizeTest` and `StopRouteAbortAfterTimeoutTest` were flaky and passed on rerun; neither touches the changed code. 🤖 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]
