shashank created CAMEL-26292:
--------------------------------
Summary: camel-core - ThrottlingInflightRoutePolicy with the
context scope ignores failed exchanges, so a consumer it suspended is never
resumed when the exchanges still inflight fail
Key: CAMEL-26292
URL: https://issues.apache.org/jira/browse/CAMEL-26292
Project: Camel
Issue Type: Bug
Components: camel-core
Reporter: shashank
Assignee: shashank
With {{scope=Context}}, {{ThrottlingInflightRoutePolicy}} (camel-support)
throttles from an event notifier: per its javadoc it "will use an EventNotifier
to listen for events when Exchanges is done". The notifier only takes
{{ExchangeCompletedEvent}} ({{ContextScopedEventNotifier.isEnabled}}, main
a090e27eb02a line 383). An exchange that is done with an exception does not
raise that event: {{DefaultUnitOfWork.done}} raises {{ExchangeFailedEvent}}
instead (lines 281-285). So with the context scope, failed exchanges never
reach {{throttle()}}, while with the route scope {{onExchangeDone}} throttles
every exchange.
The consumer is suspended when an exchange completes while more than
{{maxInflightExchanges}} are inflight, and it is only resumed by a later done
exchange. If the exchanges that are still inflight all fail (a backend outage,
which is also when inflight exchanges pile up), no event reaches the policy,
and the consumer stays suspended for good: the route consumes nothing any more,
also after the backend has recovered, until another exchange of the context
completes (in another route, or one sent by a {{ProducerTemplate}}) or the
route is restarted.
Reproduced (no sleeps, latches only):
{{from("seda:foo?concurrentConsumers=3").routePolicy(policy)}} with
{{scope=Context}}, {{maxInflightExchanges=1}}; three messages enter the route;
one completes, so the policy suspends the consumer; the two others fail. The
consumer is still suspended after both failures; with the fix it is resumed,
and a fourth message is consumed.
*Fix*: the notifier also takes {{ExchangeFailedEvent}}, and reads the exchange
through {{ExchangeEvent}}. {{DefaultUnitOfWork.done}} raises exactly one of the
two events per exchange, so no exchange is throttled twice. No option or
behaviour change for the route scope.
*Tests*: new {{ThrottlingInflightRoutePolicyContextScopeFailedExchangesTest}}
(camel-core) fails on main (3 of 3 runs) and passes with the fix. There was no
test of the context scope before.
*How it was found*: a Rocq JVM model hunt (a JVM semantics in Rocq that
executes the real class files). The kernel-checked theorem
{{context_scope_ignores_failed_exchanges}} runs the compiled
{{ContextScopedEventNotifier.isEnabled}} of main on an
{{ExchangeCompletedEvent}} and an {{ExchangeFailedEvent}} and gets {{true}} and
{{false}}; {{fix_context_scope_sees_failed_exchanges}} gets {{true}} for both
on the fix. The route-level effect was then reproduced on HotSpot with the test
above.
*Affected*: main, camel-4.22.x, camel-4.18.x and camel-4.14.x (same
{{isEnabled}}; read, not run).
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)