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

Claus Ibsen resolved CAMEL-24584.
---------------------------------
    Resolution: Fixed

Fixed in main via https://github.com/apache/camel/pull/26028 (merged as 
f899b39). Backport to camel-4.22.x in progress: 
https://github.com/apache/camel/pull/26052. Backport to camel-4.18.x skipped as 
it depends on CAMEL-24286 (PR #25217), which is not present on that branch.

_Claude Code on behalf of davsclaus_

> camel-support: BackgroundTask.schedule keeps re-running a task that has 
> completed or run out of budget
> ------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24584
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24584
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>    Affects Versions: 4.18.3, 4.20.0, 4.21.0, 4.22.0
>            Reporter: Henrik
>            Priority: Major
>             Fix For: 4.22.1, 4.23.0
>
>
> {{BackgroundTask.schedule(CamelContext, BooleanSupplier)}} submits the task 
> with
> {{scheduleWithFixedDelay}} and returns the {{Future}}, but the task never 
> cancels it. Once the task is finished, {{runTaskWrapper}} short-circuits on 
> its own latch:
> {code:java}
> if (latch.getCount() == 0) {
>     return;
> }
> {code}
> so the runnable keeps being re-run at the task interval, doing nothing, for 
> the life of the executor. This happens on both terminal paths:
> * the supplier returned {{true}}, so the task is {{Completed}};
> * the budget ran out, so the task is {{Exhausted}}.
> Cancelling is left to every caller. {{camel-sjms}} 
> ({{SimpleMessageListenerContainer}}) does cancel the future it keeps; 
> {{camel-master}} did not, which is one of the observations in CAMEL-24583 - 
> every leadership change left a repeating no-op task on the "Leadership" pool 
> for the life of the route.
> The {{Exhausted}} case cannot be fixed by the caller at all. After the budget 
> runs out the supplier is never invoked again, so nothing component-side is 
> ever given the chance to notice and cancel.
> h2. Proposed fix
> Record the future inside {{schedule()}} and cancel it on the paths where the 
> task can no longer do any work: {{Completed}}, {{Exhausted}}, and a guard for 
> the case where a task with a zero initial delay finishes before the future 
> has been published.
> The blocking {{run()}} path is deliberately left untouched: it already 
> cancels the future it owns in {{waitForTaskCompletion}}, and {{camel-sjms}} 
> branches on {{isRunning()}}, which that path controls.
> h2. Compatibility
> {{schedule()}} is public and is called from outside core. A caller that 
> inspects the returned {{Future}} will now see {{isCancelled()}} return 
> {{true}} once the task is done, where it previously stayed live forever. 
> Callers that already cancel the future themselves are unaffected. An upgrade 
> guide entry is included.
> h2. Not addressed here
> When a *caller* cancels the future instead, the task is never removed from 
> the {{TaskManagerRegistry}} - {{runTaskWrapper}} only unregisters from inside 
> a later run, which by then cannot happen. The task stays listed as {{Active}} 
> in JMX and in the {{camel/internal-tasks}} dev console until the context 
> stops. That affects {{camel-sjms}} today and {{camel-master}} after 
> CAMEL-24583, and would be better fixed by giving {{BackgroundTask}} a cancel 
> operation that also deregisters. Worth a separate issue.
> h2. References
> The behaviour dates back to CAMEL-22206, which introduced {{schedule()}} in 
> 4.13.0. Related recent work in the same class: CAMEL-24278 and CAMEL-24286.
> The change is already included in the pull request for CAMEL-24583:
> https://github.com/apache/camel/pull/26028



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

Reply via email to