daisy-consortium/pipeline-framework — pull request #42 by capitancambio (2014-02-24 19:59:26+00:00)
Title: Adding priorities to jobs

**This is an ongoing pull request, please do not merge yet!**

__First part: Scheduler and Job priorities__

___Changes on the current design___
When we agreed on the new priorities scheme we decided to have to different priorities, per client and per job. So modifications to the following classes have to be done:
Job: add priority
JobContext: add the client (now the context is client aware)
Client and related classes: moved to the framework-core.
Client: add priority.
Priority: new class in common-utils? it may belong to the framework though (TODO).
DefaultExectutionService: Now depends on a ThreadPoolExectionService (fixed size) and this have to be change to take into account the priorities.

___ThreadPoolExecutonService Design___
The main requirements we have are:
1. Some mechanism for moving up and down jobs in the priority queue.
2. Take into account the job priorities.
3. Avoid starvation.

* [UpdatablePriorityBlockingQueue] (framework-core/src/main/java/org/daisy/pipeline/job/priority/UpdatablePriorityBlockingQueue.java)
This queue implementation allows to move up and down prioritised tasks and gives a mechanism to update the priorities of the tasks waiting to be executed.

* [PriorityThreadPoolExecutor](https://github.com/daisy-consortium/pipeline-framework/blob/priority/framework-core/src/main/java/org/daisy/pipeline/job/priority/PriorityThreadPoolExecutor.java)
ThreadPoolExecutor that uses an UpdatablePriorityBlockingQueue under the hood. A part from allowing moving up and down tasks it adapts to the executing context by tracking the time that each task has spent in the queue.

* Fuzzy system:
Each job is now wrapped in fuzzy system that controls each job's final priority. This final priority is calculated in base to the time spent in the working queue (tracked by the executor itself), and the two available priorities. The system is designed so that no task will starve (i.e. a task with high priorities (job and client) that is new in the queue has less final priority than a very old task with low priorities. The system is also tested for general sanity: In the same temporal conditions, tasks with higher priorities have more final priority, and tasks that have waited longer have more final priority when the rest of the variables are the same.

The new scheduling service follows the next steps:

1. Each time a new job is submitted the waiting time is set to 0 and its overall priority is computed before being inserted into the queue.
2. Before a task is executed its waiting time is stored.
3. When enough tasks (5 by default) have been executed the average waiting time is calculated, assuring a nice adaption to the current conditions in the queue. The priorities of the rest of the tasks in the queue are updated taking into account their relative waiting time and their different priorities.
4. voila :smile: