-
Bug
-
Resolution: Done
-
Major
-
10.0.0.Alpha1
-
None
Scenario:
- The AS is configured to use a JDBC storage for EJB timers (using the H2 ExampleDS is sufficient for reproduction)
- There is a persistent calendar timer going off every few seconds
- The 'trigger' management operation is called on that timer
- The timer goes off one time extra, as expected
- The 'suspend' management operation is called on that timer
- After a few seconds, the 'activate' operation is called on that timer
- The timer will never go off again (not even by invoking 'trigger' operation)
The cause:
- Each time the timer goes off, a new java.util.TimerTask is scheduled to handle the next alarm
- When the 'trigger' operation is invoked, the TimerServiceImpl computes the timestamp of the next alarm and schedules a new TimerTask
- The problem is that this new TimerTask overwrites the one currently registered in the TimerServiceImpl, because the TimerServiceImpl assigns TimerTasks to Timers using a map: https://github.com/wildfly/wildfly/blob/10.0.0.Alpha1/ejb3/src/main/java/org/jboss/as/ejb3/timerservice/TimerServiceImpl.java#L905 - the TimerServiceImpl loses the reference to the previously registered TimerTask and doesn't cancel it
- From now on, each new alarm registers the next TimerTask, but makes TimerServiceImpl forget the previous one
- After some time, when the 'suspend' operation is called, the TimerServiceImpl cancels its stored TimerTask. However, it doesn't know that there is another scheduled elsewhere
- The TimerTask goes off during the time when the timer is suspended.
- DatabaseTimerPersistence checks whether the TimerTask can run and sets the Timer's state to IN_TIMEOUT if yes (https://github.com/wildfly/wildfly/blob/10.0.0.Alpha1/ejb3/src/main/java/org/jboss/as/ejb3/timerservice/persistence/database/DatabaseTimerPersistence.java#L395). However, this is done BEFORE checking whether the timer is suspended. DatabaseTimerPersistence commits this change. Then comes the mentioned check (https://github.com/wildfly/wildfly/blob/10.0.0.Alpha1/ejb3/src/main/java/org/jboss/as/ejb3/timerservice/task/TimerTask.java#L141) and it fails, so the Timer will not go off, but the Timer state remains IN_TIMEOUT forever!
- With every next invocation, as the timer's state remains IN_TIMEOUT, all invocations are skipped.
- clones
-
JBEAP-147 EJB timer blocked after trigger+suspend+activate operations and JDBC storage
- Closed