[ 
https://issues.apache.org/jira/browse/CAMEL-25823?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Guillaume Nodet reassigned CAMEL-25823:
---------------------------------------

    Assignee: Guillaume Nodet

> camel-core - Split and Multicast start their child producers before 
> CamelContext starts, so with the supervising route controller a producer that 
> cannot start yet fails the whole context
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25823
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25823
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>    Affects Versions: 4.22.1, 4.23.0
>            Reporter: Serdar Gökay
>            Assignee: Guillaume Nodet
>            Priority: Major
>
> With the supervising route controller enabled, a route whose producer cannot 
> start yet (for example its broker is down) is retried with back-off, and 
> Camel starts. This works for a {{to}} directly in the route. In a quick check 
> on 4.23.0 Camel also started, and the route ended up Started, with the {{to}} 
> inside filter, choice, doTry, loop, loadBalance and wireTap, and with enrich 
> and recipientList (which create their producer at runtime). When the same 
> {{to}} is inside {{split}} or {{multicast}}, the producer is started during 
> route initialization, before the CamelContext starts and outside the 
> supervising controller. The start failure then fails the CamelContext, and 
> the route is never supervised.
> *Reproduction* (plain camel-core unit test, no external system; 
> SupervisingRouteControllerMulticastProducerStartTest, ready for a PR): a 
> component whose producer fails its first two {{doStart}} calls with "Cannot 
> connect", supervising controller enabled (backOffDelay 25, backOffMaxAttempts 
> 10, initialDelay 10).
> ||Route||Result||
> |{{from(direct).to(flaky)}}|Camel starts, route retried and Started after 2 
> failed starts|
> |{{from(direct).split(body()).to(flaky)}}|{{context.start()}} throws 
> {{IllegalStateException: Cannot connect}}|
> |{{from(direct).multicast().to(flaky)}}|{{context.start()}} throws 
> {{IllegalStateException: Cannot connect}}|
> Stack of the split case:
> {noformat}
> IllegalStateException: Cannot connect
>   at ...FlakyComponent$1$1.doStart
>   at 
> org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:129)
>   at 
> org.apache.camel.support.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.start(AsyncProcessorConverterHelper.java:116)
>   at 
> org.apache.camel.impl.engine.DeferServiceStartupListener.doStart(DeferServiceStartupListener.java:63)
>   at 
> org.apache.camel.impl.engine.DeferServiceStartupListener.onCamelContextStarting(DeferServiceStartupListener.java:49)
>   at 
> org.apache.camel.impl.engine.AbstractCamelContext.doStartCamel(AbstractCamelContext.java:3190)
>   ...
>   at 
> org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:214)
> {noformat}
> We first hit this with a camel-paho-mqtt5 producer inside a split while the 
> broker host did not resolve; the same {{to}} outside the split was retried by 
> the controller. Any producer that connects in {{doStart}} behaves the same 
> way.
> *Cause* (main 04333431a65):
> # {{MulticastProcessor.doInit}} (MulticastProcessor.java:313-321) calls 
> {{wrapInErrorHandler}} for every child processor. Split and multicast both 
> use it.
> # {{wrapInErrorHandler}} starts the wrapped child right away: "must start the 
> error handler", {{ServiceHelper.startService(answer)}} 
> (MulticastProcessor.java:1213-1214). This starts the child's 
> {{SendProcessor}}.
> # {{SendProcessor.doStart}} creates the producer and adds it with 
> {{camelContext.addService(producer, true, true)}} 
> (SendProcessor.java:335-350). The context is not started yet, so 
> {{InternalServiceManager}} defers it as an early service 
> (InternalServiceManager.java:164).
> # {{DeferServiceStartupListener.onCamelContextStarting}} starts the early 
> services before any route starts, outside 
> {{DefaultSupervisingRouteController}}, and the exception fails the context.
> For a {{to}} directly in the route, the producer is started by the route 
> start, which the supervising controller runs and retries.
> *History*: The start inside {{wrapInErrorHandler}} dates from CAMEL-2360 / 
> CAMEL-3497, when the error handlers were created while processing the first 
> exchange, so the context and route were already started. Commit 7d70ad80c7d 
> ("Support for the splitter eip in lightweight mode", 2020) moved the creation 
> into {{doInit}} for the lightweight CamelContext. CAMEL-19292 removed the 
> lightweight context in 4.0, and the eager creation in {{doInit}} stayed.
> *Related*:
> * CAMEL-18319: the supervising controller should not warm up routes during 
> the normal startup, so that start errors stay under its control. This is a 
> remaining eager start.
> * CAMEL-21319: the test added there 
> (SmppTRXProducerSupervisingRouteControllerIT) shows a producer directly in 
> the route being restarted by the controller. {{lazyStartProducer}} was 
> suggested there as an alternative; it also avoids this failure, but the route 
> then starts and every message fails until the producer works, instead of the 
> route being supervised the same way as in the other EIPs.
> * CAMEL-21775 (split/multicast in onException with the supervising 
> controller) is a different problem.
> *Possible direction* (not tried): in {{doInit}} only create and initialize 
> the error handlers, and start them in {{doStart}}, which already starts 
> {{processors}} (MulticastProcessor.java:1280) and runs under the route start. 
> I can open a PR with the test, and with the fix if this direction is 
> acceptable.
> _Claude Code on behalf of etzel-mes_



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

Reply via email to