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

shashank updated CAMEL-25872:
-----------------------------
    Description: 
{{KafkaShareConsumer}} (main a0382c2a75ed) does not implement {{Suspendable}}, 
so a suspend of the CamelContext ({{CamelContext.suspend()}}, the JMX 
{{suspend}} operation of the CamelContext) stops the share consumer, and the 
resume starts it again ({{AbstractCamelContext.doResume}}, a route that does 
not support suspension is started instead of resumed).

When the consumer starts, it hands its fetch tasks to the component instead of 
submitting them when the CamelContext is not started (CAMEL-23023, so that no 
record is processed before the CamelContext is fully started):

{code:java}
if (!endpoint.getCamelContext().isStarted()) {
    endpoint.getComponent().pendingConsumer(() -> executor.submit(task));
} else {
    executor.submit(task);
}
{code}

{{AbstractKafkaComponent}} submits the pending tasks from 
{{onCamelContextFullyStarted}}. During a resume the CamelContext is not in the 
Started state ({{BaseService.resume}} sets {{STARTING}} until {{doResume}} 
returns), so the tasks are added to the pending list, and a resume does not 
call the startup listeners again. The tasks are never submitted: the route 
reports Started, no share consumer is created and no record is consumed until 
the route or the CamelContext is restarted. Nothing is logged; the consumer 
health check (when enabled) reports the route DOWN, as its tasks are not 
connected.

The Kafka consumer of camel-kafka implements {{Suspendable}} and is paused and 
resumed instead, so it is not affected.

*Fix*: {{AbstractKafkaComponent}} remembers that it was notified that the 
CamelContext started (reset when the component stops), and a new 
{{startConsumer(Runnable)}} runs the task at once in that case or when the 
CamelContext is started, or keeps it pending until the notification. The 
CamelContext is still checked because a component added with {{addComponent}} 
to a started CamelContext is not registered as a startup listener, so it is 
never notified. The share consumer and the Kafka consumer use it instead of 
checking whether the CamelContext is started, so the startup of a consumer 
before the CamelContext is fully started is delayed as before.

*Tests*: new {{KafkaShareConsumerSuspendResumeTest}} (the 
{{RecordingShareConsumer}} of {{KafkaShareConsumerTest}}, a 
{{MockShareConsumer}}): suspend and resume the CamelContext, then add a record. 
On main it fails: the route is Started, but no new share consumer is created 
after the resume ({{ConditionTimeout}} after 10 seconds waiting for the second 
consumer to subscribe). With the fix it passes. A second test adds a 
{{KafkaShareComponent}} with {{addComponent}} to the started CamelContext and 
consumes with it (passes on main; it guards the {{isStarted()}} check of 
{{startConsumer}}). Unit tests with the fix: camel-kafka-common 11, camel-kafka 
225 (1 skipped), camel-kafka-share 29, 0 failures.

*How it was found*: review of the deferred start of the Kafka consumers 
({{AbstractKafkaComponent.pendingConsumers}}) against the CamelContext 
lifecycle, then the JUnit test above.

*Affected*: main and 4.23.0 / camel-4.23.x, the release that added 
camel-kafka-share (CAMEL-25029), with the same code (read, not run).

_Filed with Claude Code on behalf of allthingssecurity._


  was:
{{KafkaShareConsumer}} (main a0382c2a75ed) does not implement {{Suspendable}}, 
so a suspend of the CamelContext ({{CamelContext.suspend()}}, the JMX 
{{suspend}} operation of the CamelContext) stops the share consumer, and the 
resume starts it again ({{AbstractCamelContext.doResume}}, a route that does 
not support suspension is started instead of resumed).

When the consumer starts, it hands its fetch tasks to the component instead of 
submitting them when the CamelContext is not started (CAMEL-23023, so that no 
record is processed before the CamelContext is fully started):

{code:java}
if (!endpoint.getCamelContext().isStarted()) {
    endpoint.getComponent().pendingConsumer(() -> executor.submit(task));
} else {
    executor.submit(task);
}
{code}

{{AbstractKafkaComponent}} submits the pending tasks from 
{{onCamelContextFullyStarted}}. During a resume the CamelContext is not in the 
Started state ({{BaseService.resume}} sets {{STARTING}} until {{doResume}} 
returns), so the tasks are added to the pending list, and a resume does not 
call the startup listeners again. The tasks are never submitted: the route 
reports Started, no share consumer is created and no record is consumed until 
the route or the CamelContext is restarted. Nothing is logged; the consumer 
health check (when enabled) reports the route DOWN, as its tasks are not 
connected.

The Kafka consumer of camel-kafka implements {{Suspendable}} and is paused and 
resumed instead, so it is not affected.

*Fix*: {{AbstractKafkaComponent}} remembers that it was notified that the 
CamelContext started (reset when the component stops), and a new 
{{startConsumer(Runnable)}} runs the task at once in that case, or keeps it 
pending until the notification. The share consumer and the Kafka consumer use 
it instead of checking whether the CamelContext is started, so the startup of a 
consumer before the CamelContext is fully started is delayed as before.

*Tests*: new {{KafkaShareConsumerSuspendResumeTest}} ({{MockShareConsumer}} 
based, as {{KafkaShareConsumerTest}}): suspend and resume the CamelContext, 
then add a record. On main it fails: the route is Started, but no new share 
consumer is created after the resume ({{ConditionTimeout}} after 10 seconds 
waiting for the second consumer to subscribe). With the fix it passes. Unit 
tests with the fix: camel-kafka-common 11, camel-kafka 225 (1 skipped), 
camel-kafka-share 28, 0 failures.

*How it was found*: review of the deferred start of the Kafka consumers 
({{AbstractKafkaComponent.pendingConsumers}}) against the CamelContext 
lifecycle, then the JUnit test above.

*Affected*: main and 4.23.0 / camel-4.23.x, the release that added 
camel-kafka-share (CAMEL-25029), with the same code (read, not run).

_Filed with Claude Code on behalf of allthingssecurity._



> camel-kafka-share - after the CamelContext is suspended and resumed, the 
> share consumer never consumes again (the route stays Started)
> --------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25872
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25872
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-kafka
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> {{KafkaShareConsumer}} (main a0382c2a75ed) does not implement 
> {{Suspendable}}, so a suspend of the CamelContext 
> ({{CamelContext.suspend()}}, the JMX {{suspend}} operation of the 
> CamelContext) stops the share consumer, and the resume starts it again 
> ({{AbstractCamelContext.doResume}}, a route that does not support suspension 
> is started instead of resumed).
> When the consumer starts, it hands its fetch tasks to the component instead 
> of submitting them when the CamelContext is not started (CAMEL-23023, so that 
> no record is processed before the CamelContext is fully started):
> {code:java}
> if (!endpoint.getCamelContext().isStarted()) {
>     endpoint.getComponent().pendingConsumer(() -> executor.submit(task));
> } else {
>     executor.submit(task);
> }
> {code}
> {{AbstractKafkaComponent}} submits the pending tasks from 
> {{onCamelContextFullyStarted}}. During a resume the CamelContext is not in 
> the Started state ({{BaseService.resume}} sets {{STARTING}} until 
> {{doResume}} returns), so the tasks are added to the pending list, and a 
> resume does not call the startup listeners again. The tasks are never 
> submitted: the route reports Started, no share consumer is created and no 
> record is consumed until the route or the CamelContext is restarted. Nothing 
> is logged; the consumer health check (when enabled) reports the route DOWN, 
> as its tasks are not connected.
> The Kafka consumer of camel-kafka implements {{Suspendable}} and is paused 
> and resumed instead, so it is not affected.
> *Fix*: {{AbstractKafkaComponent}} remembers that it was notified that the 
> CamelContext started (reset when the component stops), and a new 
> {{startConsumer(Runnable)}} runs the task at once in that case or when the 
> CamelContext is started, or keeps it pending until the notification. The 
> CamelContext is still checked because a component added with {{addComponent}} 
> to a started CamelContext is not registered as a startup listener, so it is 
> never notified. The share consumer and the Kafka consumer use it instead of 
> checking whether the CamelContext is started, so the startup of a consumer 
> before the CamelContext is fully started is delayed as before.
> *Tests*: new {{KafkaShareConsumerSuspendResumeTest}} (the 
> {{RecordingShareConsumer}} of {{KafkaShareConsumerTest}}, a 
> {{MockShareConsumer}}): suspend and resume the CamelContext, then add a 
> record. On main it fails: the route is Started, but no new share consumer is 
> created after the resume ({{ConditionTimeout}} after 10 seconds waiting for 
> the second consumer to subscribe). With the fix it passes. A second test adds 
> a {{KafkaShareComponent}} with {{addComponent}} to the started CamelContext 
> and consumes with it (passes on main; it guards the {{isStarted()}} check of 
> {{startConsumer}}). Unit tests with the fix: camel-kafka-common 11, 
> camel-kafka 225 (1 skipped), camel-kafka-share 29, 0 failures.
> *How it was found*: review of the deferred start of the Kafka consumers 
> ({{AbstractKafkaComponent.pendingConsumers}}) against the CamelContext 
> lifecycle, then the JUnit test above.
> *Affected*: main and 4.23.0 / camel-4.23.x, the release that added 
> camel-kafka-share (CAMEL-25029), with the same code (read, not run).
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to