shashank created CAMEL-25848:
--------------------------------

             Summary: camel-quartz - CronScheduledRoutePolicy / 
SimpleScheduledRoutePolicy: a consumer that cannot be suspended (netty, mina, 
mllp, paho, ...) is stopped by the scheduled suspend and never started again by 
the scheduled resume
                 Key: CAMEL-25848
                 URL: https://issues.apache.org/jira/browse/CAMEL-25848
             Project: Camel
          Issue Type: Bug
          Components: camel-quartz
            Reporter: shashank
            Assignee: shashank


{{ScheduledRoutePolicy.onJobExecute}} (camel-quartz, main 20cdb309f7d0, lines 
64-99) is shared by {{CronScheduledRoutePolicy}} and 
{{SimpleScheduledRoutePolicy}}. The scheduled suspend calls 
{{suspendOrStopConsumer(route.getConsumer())}}, which suspends a 
{{Suspendable}} consumer and *stops* any other consumer 
({{ServiceHelper.suspendService}}). The route itself stays {{Started}}.

The scheduled resume and start only look for a suspended consumer:

{code:java}
} else if (action == Action.RESUME) {
    if (routeStatus == ServiceStatus.Started) {
        if (ServiceHelper.isSuspended(route.getConsumer())) {
            resumeOrStartConsumer(route.getConsumer());
        } else {
            LOG.warn("The Consumer {} is not suspended and cannot be resumed.", 
route.getConsumer());
        }
{code}

The START action of a {{Started}} route has the same {{isSuspended}} check. A 
stopped consumer is not suspended, so after the first scheduled suspend a 
consumer that is not {{Suspendable}} is never started again: every scheduled 
resume logs the WARN above, and the route stays {{Started}} without a consumer 
until someone restarts the route or the application.

Consumers that are not {{Suspendable}} on main include those of camel-netty 
(TCP/UDP), camel-mina, camel-mllp, camel-paho, camel-paho-mqtt5, camel-grpc, 
camel-azure-servicebus, camel-azure-eventhubs, camel-google-pubsub, 
camel-aws2-kinesis (KCL), camel-debezium and camel-mongodb (tailable cursor, 
change streams). The page of the policy describes exactly this use: suspension 
stops the consumer "from listening on a given port" and resumption makes the 
route accept requests again. For example a nightly maintenance window 
({{routeSuspendTime}} / {{routeResumeTime}}) on a netty or MLLP listener leaves 
the port closed for good after the first night.

{{resumeOrStartConsumer}} itself already starts a stopped consumer that is not 
{{Suspendable}} (the throttling route policies rely on it); only the guard in 
front of it is too narrow.

*Fix*: a scheduled resume, and a scheduled start of a {{Started}} route, resume 
or start the consumer when it is suspended *or stopped*. Nothing else changes: 
a stopped route is still started with {{startRoute}}, and a running consumer 
still gets the WARN on resume.

*Tests*: new {{ScheduledRoutePolicyNonSuspendableConsumerTest}} (2 tests) with 
a test endpoint whose consumer is a plain {{DefaultConsumer}} (not 
{{Suspendable}}). {{scheduledResumeStartsConsumerThatWasStoppedBySuspend}} uses 
a {{SimpleScheduledRoutePolicy}} with a suspend date and a resume date and real 
Quartz triggers; on main the suspend stops the consumer and the resume never 
starts it ({{ConditionTimeoutException ... consumer should be started again ==> 
expected: <true> but was: <false> within 5 seconds}}). 
{{scheduledStartStartsConsumerThatWasStoppedBySuspend}} runs the SUSPEND and 
START actions of a {{CronScheduledRoutePolicy}} as the scheduler would; on main 
it fails with {{consumer should be started again ==> expected: <true> but was: 
<false>}}. Both pass with the fix. camel-quartz unit tests with the fix: 110 
run, 0 failures.

*How it was found*: a review of the route policies that suspend a consumer, 
comparing how each one undoes {{suspendOrStopConsumer}} (the throttling 
policies call {{resumeOrStartConsumer}} directly; the scheduled policies guard 
it with {{isSuspended}}). The JUnit tests above are the evidence; it was not 
run with a netty or MLLP route.

*Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x 
(the same {{isSuspended}} checks in {{ScheduledRoutePolicy}}, lines 72 and 90, 
and {{NettyConsumer}} is not {{Suspendable}} on each; read, not run). The check 
on the START action came with CAMEL-5555 (start of a suspended route).

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to