Cube capacity scheduler

Implements the Cube Capacity Scheduler and Agent.

This models an agent as a constrained actor that has a maximum value of that resource that it can allocate. Jobs must define a default value for this resource (or pass it in as a parameter) and the agent will continue accepting jobs and creating the appropriate worker to handle the job until it has allocated all of that resource. Combining the cost of a job and the capacity of a worker allows tuning how many of each worker may run in parallel.

Currently this resource is called "memory" and there is only one of them. This is a little simplistic but can be expanded to allow definition of arbitrary resource constraints and requirements for agents and jobs in the future.

Defining a default memory value for a job is enforced - enqueuing a job that lacks this parameter will fail.

This also adds a constraint that is used in the Cube Capacity Agent that ensures that older jobs get processed before newer ones (assuming that the agent has free capacity, otherwise they will be scheduled as soon as that capacity becomes available). This gives no guarantee that a job will be processed in a timely manner, only that it eventually will be processed if enough resources become available. This change is not specific to the Cube Capacity Agent and we should consider making it the default comparator in place of the JobComparator which prioritises jobs purely by their ID.