allthingssecurity opened a new pull request, #27249:
URL: https://github.com/apache/camel/pull/27249

   # Description
   
   [CAMEL-25252](https://issues.apache.org/jira/browse/CAMEL-25252)
   
   The timer consumers of the same timer name share one `java.util.Timer`. 
`TimerComponent` reference counts it: `getTimer` creates it or increments the 
count, and `removeTimer` decrements the count and cancels the `Timer` at 0. 
`TimerConsumer` takes a reference only for a delay of 0 or more. A consumer 
with a negative delay (`delay=-1`, fire as fast as possible, CAMEL-9249) fires 
from its own executor and never calls `getTimer`. But `doStop` always calls 
`removeTimer`.
   
   So stopping a negative-delay consumer releases a reference it never took. 
When the reference belongs to another consumer, the shared `Timer` is cancelled 
while that consumer is running: its route stays Started but never fires again, 
and nothing is logged. Example: `timer:tick?period=1000` in one route and 
`timer:tick?delay=-1&repeatCount=1` in another, then the second route is 
stopped or restarted.
   
   This change: `TimerConsumer` remembers whether it took the timer (set where 
`getTimer` is called, in `doStart` and `onCamelContextStarted`), and `doStop` 
releases it only then. The flag is set right after `getTimer`, before the task 
is scheduled, so a reference taken when scheduling fails is still released. 
This also covers a consumer with a delay of 0 or more that is stopped before 
the CamelContext has started, which has not taken the timer yet either.
   
   Tests:
   - New `TimerNegativeDelayStopRouteTest` in camel-core, in the style of 
`TimerMultipleConsumerStopRouteTest`. Route `foo` is 
`timer:mytimer?period=100`, and route `bar` is 
`timer:mytimer?delay=-1&repeatCount=1`, started by the test. After `bar` fired, 
it is stopped once (and in the second test stopped, started and stopped again), 
and `foo` must keep firing.
   - Without the change both tests fail: `mock://foo Received message count 0, 
expected at least 2`.
   - With the change, the camel-core timer tests pass: 19 classes, 34 tests, 0 
failures. camel-timer has no tests of its own.
   
   Found with a TLA+ model of the reference count, with consumers that do and 
do not take the timer, started and stopped in any order. The model cancels a 
started consumer's timer as soon as a negative-delay consumer is stopped, and 
holds with the fix. I then reproduced it with the real component.
   
   # Target
   
   - [x] I checked that the commit is targeting the correct branch (Camel 4 
uses the `main` branch)
   
   # Tracking
   - [x] If this is a large change, bug fix, or code improvement, I checked 
there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for 
the change (usually before you start working on it).
   
   # Apache Camel coding standards and style
   
   - [x] I checked that each commit in the pull request has a meaningful 
subject line and body.
   - [ ] I have run `mvn clean install -DskipTests` locally from root folder 
and I have committed all auto-generated changes.
     (I built and tested the affected module, including the formatter and 
import-sort plugins. I did not run the full root build.)
   
   # AI-assisted contributions
   
   - [x] If this PR includes AI-generated code, commits have proper 
co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR 
description identifies the AI tool used.
     This PR was prepared with Claude Code (Claude Opus 5.5). The commit 
carries a `Co-Authored-By` trailer.
   
   _Claude Code on behalf of allthingssecurity_
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to