package hudson.model.queue; import hudson.ExtensionList; import hudson.ExtensionPoint; import hudson.init.Initializer; import jenkins.model.Jenkins; import hudson.model.LoadBalancer; import hudson.model.Queue; import hudson.model.Queue.BuildableItem; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.logging.Logger; import static hudson.init.InitMilestone.JOB_LOADED; /** * Singleton extension point for sorting buildable items * * @since 1.343 */ public abstract class QueueSorter implements ExtensionPoint { /** * A comparator that sorts {@link Queue.BlockedItem} instances based on how long they have been in the queue. * (We want the time since in queue by default as blocking on upstream/downstream considers waiting items * also and thus the blocking starts once the task is in the queue not once the task is buildable) * * @since 1.618 */ public static final Comparator<Queue.BlockedItem> DEFAULT_BLOCKED_ITEM_COMPARATOR = new Comparator<Queue.BlockedItem>() { @Override public int compare(Queue.BlockedItem o1, Queue.BlockedItem o2) { return Long.compare(o1.getInQueueSince(), o2.getInQueueSince()); } }; /** * Sorts the buildable items list. The items at the beginning will be executed * before the items at the end of the list. * * @param buildables * List of buildable items in the queue. Never null. */ public abstract void sortBuildableItems(List<BuildableItem> buildables); /** * Sorts the blocked items list. The items at the beginning will be considered for removal from the blocked state * before the items at the end of the list. * * @param blockedItems * List of blocked items in the queue. Never null. * @since 1.618 */ public void sortBlockedItems(List<Queue.BlockedItem> blockedItems) { Collections.sort(blockedItems, DEFAULT_BLOCKED_ITEM_COMPARATOR); } /** * All registered {@link QueueSorter}s. Only the first one will be picked up, * unless explicitly overridden by {@link Queue#setSorter(QueueSorter)}. */ public static ExtensionList<QueueSorter> all() { return ExtensionList.lookup(QueueSorter.class); } /** * Installs the default queue sorter. * * {@link Queue#Queue(LoadBalancer)} is too early to do this */ @Initializer(after=JOB_LOADED) public static void installDefaultQueueSorter() { ExtensionList<QueueSorter> all = all(); if (all.isEmpty()) return; Queue q = Jenkins.getInstance().getQueue(); if (q.getSorter()!=null) return; // someone has already installed something. leave that alone. q.setSorter(all.get(0)); if (all.size()>1) LOGGER.warning("Multiple QueueSorters are registered. Only the first one is used and the rest are ignored: "+all); } private static final Logger LOGGER = Logger.getLogger(QueueSorter.class.getName()); }