You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (Jira)" <ji...@apache.org> on 2026/09/02 17:58:00 UTC
[jira] [Resolved] (CAMEL-24584) camel-support: BackgroundTask.schedule keeps re-running a task that has completed or run out of budget
[ 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)