Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TaskScheduler breaks when 2 tasks with identical timestamps are added #67

Closed
pgbsl opened this issue Aug 12, 2016 · 0 comments
Closed

Comments

@pgbsl
Copy link

pgbsl commented Aug 12, 2016

If two tasks (e.g. 2 PoolShrinkingTask instances) are scheduled, via the TasksScheduler.addTask( ) method, and the tasks have an identical executionTime, then the second task will not be added to the scheduler's task set (even though debug logging indicates that the task has actually been scheduled).

Given that tasks are self scheduling, this means that no further tasks of this type will be scheduled for this resource.

As a concrete example, consider the following scenario.

DataSoure1 and DataSource2 are both being managed by Btx TM. The bitronix-task-scheduler thread attempts to schedule pool shrinking for both data sources

2016/08/11 11:51:28.384 DEBUG bitronix-task-scheduler TaskScheduler - scheduling pool shrinking task on an XAPool of resource DataSource1 with 5 connection(s) (4 still available) for Thu Aug 11 11:52:28 BST 2016
2016/08/11 11:51:28.384 DEBUG bitronix-task-scheduler TaskScheduler - task added? true
...
...
2016/08/11 11:51:28.384 DEBUG bitronix-task-scheduler TaskScheduler - scheduling pool shrinking task on an XAPool of resource DataSource2 with 1 connection(s) (0 still available) for Thu Aug 11 11:52:28 BST 2016
2016/08/11 11:51:28.384 DEBUG bitronix-task-scheduler TaskScheduler - task added? false

The above log snippet shows the Bitronix logging for scheduling a PoolShrinkingTask for each datasource. Note that the timestamps are identical (see the logging timestamps at the start of each line and you will see milliseconds are identical). The second line in each log pair above shows some diagnostic logging that I have added. The boolean value is the result of the call to add on the taskScheduler's Set.

This is happening due a combination of the Set implementation (ConcurrentSkipListSet) and the Task objects compareTo implementation which compares based upon executionTime.

This Set implementation uses the result of compareTo to both order the set, and decide if the value is already in the Set.

The net result of this, is that we have pools with a small minPoolSize, that never shrink back down again, if the duplicate timestamp issue occurs. I assume, but have not verified, that this will hold for transaction timeouts as well.

I'm assuming that the Set implementation is the correct implementation for this use-case, so I think that the best approach to fix this issue is to look at the Comparator. The following implementation will fix this, as it uses a discriminator (UUID) to decide the result, in the case of the timestamps being equal.

    public int compareTo(Task otherTask) {
        int compareResult = this.executionTime.compareTo(otherTask.executionTime);

        if (compareResult == 0) {
            compareResult = uniqueId.compareTo(otherTask.getUniqueId());
        }
        return compareResult;
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant