class TaskMigrationDescheduler {

    Optional<Pair<Node, List<Task>>> nextBestMatch() {
        if (evictionQuotaTracker.getSystemEvictionQuota() <= 0) {
            return Optional.empty();
        }

        return evacuatedAgentsAllocationTracker.getRemovableAgentsById().values().stream()
                .map(i -> Pair.of(i, computeFitness(i)))
                .filter(p -> p.getRight().getLeft() > 0)
                .max(Comparator.comparingDouble(p -> p.getRight().getLeft()))
                .map(p -> {
                    Node agent = p.getLeft();
                    List<Task> tasks = p.getRight().getRight();

                    tasks.forEach(task -> {
                        evacuatedAgentsAllocationTracker.descheduled(task);
                        evictionQuotaTracker.consumeQuota(task.getJobId());
                    });

                    return Pair.of(agent, tasks);
                });
    }

      TaskMigrationDescheduler(Map<String, TaskRelocationPlan> plannedAheadTaskRelocationPlans,
                             EvacuatedAgentsAllocationTracker evacuatedAgentsAllocationTracker,
                             EvictionQuotaTracker evictionQuotaTracker,
                             Map<String, Job<?>> jobsById,
                             Map<String, Task> tasksById,
                             TitusRuntime titusRuntime);

}