shashank created CAMEL-25839:
--------------------------------

             Summary: camel-kamelet - toD with cacheSize=-1 creates a route 
from the Kamelet template for every message and never removes it
                 Key: CAMEL-25839
                 URL: https://issues.apache.org/jira/browse/CAMEL-25839
             Project: Camel
          Issue Type: Bug
          Components: camel-kamelet
            Reporter: shashank
            Assignee: shashank


With toD (or recipientList) and {{cacheSize=-1}}, every call resolves a new 
endpoint, which is stopped and discarded after use. The toD documentation 
recommends this when the dynamic endpoint is different for every message, so 
that Camel does not keep the endpoints and producers in memory.

For a Kamelet this does not work. Each new {{kamelet:}} endpoint creates a 
route from the template when it is initialized ({{KameletComponent}}, the 
anonymous {{KameletEndpoint}} subclass in {{createEndpoint}} calls 
{{lifecycleHandler.track}}, which calls {{addRouteFromKamelet}} with a new uuid 
in the route id, main 20cdb309f7d0). When toD discards the endpoint, nothing 
removes that route:

{code:java}
from("direct:start")
    .toD("kamelet:prefix?value=${header.id}", -1)
    .to("mock:result");
{code}

So every message leaves one more route in the CamelContext, together with its 
{{kamelet:source}} endpoint in the endpoint registry (and the route and 
processor MBeans when JMX is enabled). This happens even when every message 
uses the same parameter values, as each call gets a new endpoint and a new 
route id. The routes are never used again (the producer of a later call sends 
to the route of its own endpoint), and they are only removed when the 
CamelContext stops. A route that calls a Kamelet like this grows memory without 
bound.

*Fix*: the Kamelet endpoint remembers the route it created while the context 
runs, and when the endpoint is shut down (which toD and recipientList do for a 
discarded endpoint), it stops and removes that route. The route's private 
{{kamelet:source}} endpoint is removed with it. Endpoints kept by the endpoint 
registry (toD with a cache, the default) are not shut down while the context 
runs, so their routes are kept as before; endpoints that are only stopped are 
not affected; nothing is removed while the context stops. Removing such a route 
logs the usual INFO lines of a route stop and removal.

*Tests*: new {{KameletToDRoutesNotKeptTest}} (3 tests). 
{{routesOfDiscardedKameletEndpointsAreRemoved}} (50 messages, 50 distinct 
values, toD with cacheSize=-1) fails on main: {{routes created by the Kamelet 
and still kept after 50 calls ==> expected: <0> but was: <50>}}; it also checks 
every reply and that only the 3 endpoints of the routes stay registered. 
{{sameValueEveryTimeDoesNotKeepRoutes}} (50 messages, one value) fails on main: 
{{expected: <0> but was: <50>}}. {{cachedKameletEndpointsKeepTheirRoutes}} (toD 
with the default cache) passes on main and with the fix: the 2 routes of the 2 
cached endpoints are kept and reused. camel-kamelet unit tests with the fix: 
143 run, 0 failures, 3 skipped.

*How it was found*: a sweep for state that grows per message (routes, 
endpoints, services and listeners created on a message path and never removed), 
then the JUnit test above.

*Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x, camel-4.14.x and 
camel-4.10.x (the same route creation in the endpoint and no removal; read, not 
run). With toD and the default cache, a Kamelet still keeps one route per 
distinct parameter value, as the endpoints are kept by the registry; that is 
not changed here.

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to