shashank created CAMEL-26286:
--------------------------------

             Summary: camel-disruptor - removing one of the routes that use a 
disruptor endpoint shuts down its disruptor, so the other routes stop receiving 
and producers fail with "Disruptor was not started"
                 Key: CAMEL-26286
                 URL: https://issues.apache.org/jira/browse/CAMEL-26286
             Project: Camel
          Issue Type: Bug
          Components: camel-disruptor
            Reporter: shashank
            Assignee: shashank


Every route and producer that uses the same {{disruptor:}} uri shares one 
{{DisruptorEndpoint}}. When a route is removed, the core stops and shuts down 
the endpoint of its consumer ({{RouteService.doShutdown}}), also when other 
routes still consume from it or send to it. {{DisruptorEndpoint.doStop}} then 
calls {{DisruptorReference.removeEndpoint}}, which shuts down the disruptor and 
its executor when this was the only endpoint of the reference: all the routes 
of one uri share one endpoint, and only another uri with the same queue name 
(other options) has another endpoint on the same reference (main 36bebb520a63, 
{{DisruptorEndpoint}} line 271, {{DisruptorReference}} lines 422-436).

Example: three routes {{from("disruptor:orders?multipleConsumers=true")}}; one 
of them is stopped and removed (a route template removed, a reload, 
JMX/controlbus). The two other routes receive nothing any more, and every send 
to {{disruptor:orders?multipleConsumers=true}} fails with 
{{IllegalStateException: Disruptor was not started}} (caused by 
{{DisruptorNotStartedException: Disruptor is not yet started or already shut 
down.}}). A {{CamelContext.stop()}} afterwards takes about 10 seconds (event 
handlers that do not stop are waited for), with a {{RuntimeException: 
java.lang.InterruptedException}} from a disruptor thread.

camel-seda has the same sharing and guards against it: {{SedaEndpoint.stop()}} 
and {{shutdown()}} do nothing while the endpoint still has consumers or 
producers. The same three-route scenario on 
{{seda:orders?multipleConsumers=true}} keeps delivering to the other two routes.

*Fix*: {{DisruptorEndpoint}} overrides {{stop()}} and {{shutdown()}} like 
{{SedaEndpoint}}, but only for consumers: they do nothing (DEBUG log) while 
other consumers still use the endpoint, so the disruptor stays up for them. 
Without consumers the endpoint stops and shuts down as before. Producers are 
deliberately not counted: a producer of a removed route's uri (such as a cached 
{{ProducerTemplate}} producer) would otherwise keep the old endpoint in the 
disruptor, and its replacement (the endpoint is removed from the registry when 
no other route uses it) could not join it ({{DisruptorReference}} keeps its 
endpoints in a set based on {{equals}}, i.e. on the uri), which broke 
{{DisruptorRemoveRouteThenAddAgainTest}}. disruptor-vm endpoints inherit the 
change.

*Tests*: new {{DisruptorRemoveRouteOfSharedEndpointTest}}: 
{{removingOneOfSeveralConsumersKeepsTheOthersConsuming}} fails on main with the 
exception above (3 runs); 
{{consumerRouteRemovedAndAddedAgainWhileAProducerRouteUsesTheQueue}} (a reload 
of the consumer route while a producer route stays) passes on main and with the 
fix; it is a control for the path the fix leaves unchanged. With the fix the 
module has 120 tests, 0 failures.

*How it was found*: a random lifecycle-sequence harness (stop, start, suspend, 
resume, remove and add of several consumer routes on shared endpoints, checking 
after each step which routes receive a probe message) run over seda, disruptor, 
timer, scheduler and other consumers; it shrank the failing sequence to a 
single remove. The same harness found nothing for seda.

*Affected*: main, camel-4.22.x, camel-4.18.x and camel-4.14.x (same 
{{DisruptorEndpoint.doStop}} and core {{RouteService.doShutdown}}; read, not 
run).

_Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to