diff --git a/src/main/java/hudson/plugins/throttleconcurrents/ThrottleJobProperty.java b/src/main/java/hudson/plugins/throttleconcurrents/ThrottleJobProperty.java index f913a885..faf6536a 100644 --- a/src/main/java/hudson/plugins/throttleconcurrents/ThrottleJobProperty.java +++ b/src/main/java/hudson/plugins/throttleconcurrents/ThrottleJobProperty.java @@ -44,20 +44,22 @@ public class ThrottleJobProperty extends JobProperty> { private String throttleOption; private transient boolean throttleConfiguration; private @CheckForNull ThrottleMatrixProjectOptions matrixOptions; + private boolean blockedByCategory; /** * Store a config version so we're able to migrate config on various * functionality upgrades. */ private Long configVersion; - + @DataBoundConstructor public ThrottleJobProperty(Integer maxConcurrentPerNode, Integer maxConcurrentTotal, List categories, boolean throttleEnabled, String throttleOption, - @CheckForNull ThrottleMatrixProjectOptions matrixOptions + @CheckForNull ThrottleMatrixProjectOptions matrixOptions, + boolean blockedByCategory ) { this.maxConcurrentPerNode = maxConcurrentPerNode == null ? 0 : maxConcurrentPerNode; this.maxConcurrentTotal = maxConcurrentTotal == null ? 0 : maxConcurrentTotal; @@ -65,6 +67,7 @@ public ThrottleJobProperty(Integer maxConcurrentPerNode, this.throttleEnabled = throttleEnabled; this.throttleOption = throttleOption; this.matrixOptions = matrixOptions; + this.blockedByCategory = blockedByCategory; } @@ -131,7 +134,11 @@ public String getThrottleOption() { public List getCategories() { return categories; } - + + public boolean isBlockedByCategory() { + return blockedByCategory; + } + public Integer getMaxConcurrentPerNode() { if (maxConcurrentPerNode == null) maxConcurrentPerNode = 0; diff --git a/src/main/java/hudson/plugins/throttleconcurrents/ThrottleQueueTaskDispatcher.java b/src/main/java/hudson/plugins/throttleconcurrents/ThrottleQueueTaskDispatcher.java index eb1abece..38f6c797 100644 --- a/src/main/java/hudson/plugins/throttleconcurrents/ThrottleQueueTaskDispatcher.java +++ b/src/main/java/hudson/plugins/throttleconcurrents/ThrottleQueueTaskDispatcher.java @@ -1,5 +1,6 @@ package hudson.plugins.throttleconcurrents; + import hudson.Extension; import hudson.matrix.MatrixConfiguration; import hudson.matrix.MatrixProject; @@ -18,6 +19,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; + import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -153,6 +155,11 @@ else if (tjp.getThrottleOption().equals("category")) { // Double check category itself isn't null if (category != null) { + // Check if this job is blocked by category + if (isBlockedByCategory(task, categoryProjects)) { + return CauseOfBlockage.fromMessage(Messages._ThrottleQueueTaskDispatcher_BlockedByCategory(catNm)); + } + if (category.getMaxConcurrentTotal().intValue() > 0) { int maxConcurrentTotal = category.getMaxConcurrentTotal().intValue(); int totalRunCount = 0; @@ -178,6 +185,35 @@ else if (tjp.getThrottleOption().equals("category")) { return null; } + private boolean isBlockedByCategory(Task task, List> categoryProjects) { + ThrottleJobProperty buildProperty = getThrottleJobProperty(task); + if (buildProperty.isBlockedByCategory()) { + return areOtherProjectsInCategoryBuilding(task, categoryProjects); + } + return false; + } + + private boolean areOtherProjectsInCategoryBuilding(Task task, List> categoryProjects) { + for (AbstractProject catProj : categoryProjects) { + if (!task.equals(catProj)) { + if (isBlockingProjectBuilding(catProj)) { + return true; + } + } + } + return false; + } + + private boolean isBlockingProjectBuilding(AbstractProject catProj) { + ThrottleJobProperty catProjThrottleProperty = catProj.getProperty(ThrottleJobProperty.class); + if (!catProjThrottleProperty.isBlockedByCategory()) { + if (catProj.isBuilding() || catProj.isInQueue()) { + return true; + } + } + return false; + } + @CheckForNull private ThrottleJobProperty getThrottleJobProperty(Task task) { if (task instanceof AbstractProject) { diff --git a/src/main/resources/hudson/plugins/throttleconcurrents/Messages.properties b/src/main/resources/hudson/plugins/throttleconcurrents/Messages.properties index 949b92e3..3eea533b 100644 --- a/src/main/resources/hudson/plugins/throttleconcurrents/Messages.properties +++ b/src/main/resources/hudson/plugins/throttleconcurrents/Messages.properties @@ -1,5 +1,6 @@ ThrottleQueueTaskDispatcher.MaxCapacityOnNode=Already running {0} builds on node ThrottleQueueTaskDispatcher.MaxCapacityTotal=Already running {0} builds across all nodes ThrottleQueueTaskDispatcher.BuildPending=A build is pending launch +ThrottleQueueTaskDispatcher.BlockedByCategory=Build is blocked by other jobs in category {0} ThrottleMatrixProjectOptions.DisplayName=Additional options for Matrix projects \ No newline at end of file diff --git a/src/main/resources/hudson/plugins/throttleconcurrents/ThrottleJobProperty/config.jelly b/src/main/resources/hudson/plugins/throttleconcurrents/ThrottleJobProperty/config.jelly index e18c2cf3..57bbef84 100644 --- a/src/main/resources/hudson/plugins/throttleconcurrents/ThrottleJobProperty/config.jelly +++ b/src/main/resources/hudson/plugins/throttleconcurrents/ThrottleJobProperty/config.jelly @@ -28,6 +28,9 @@ + + + diff --git a/src/test/java/hudson/plugins/throttleconcurrents/ThrottleJobPropertyTest.java b/src/test/java/hudson/plugins/throttleconcurrents/ThrottleJobPropertyTest.java index 47f73fbc..f16d8cfb 100644 --- a/src/test/java/hudson/plugins/throttleconcurrents/ThrottleJobPropertyTest.java +++ b/src/test/java/hudson/plugins/throttleconcurrents/ThrottleJobPropertyTest.java @@ -21,11 +21,11 @@ public void testGetCategoryProjects() throws Exception { String alpha = "alpha", beta = "beta", gamma = "gamma"; // category names FreeStyleProject p1 = createFreeStyleProject("p1"); FreeStyleProject p2 = createFreeStyleProject("p2"); - p2.addProperty(new ThrottleJobProperty(1, 1, Arrays.asList(alpha), false, THROTTLE_OPTION_CATEGORY, ThrottleMatrixProjectOptions.DEFAULT)); + p2.addProperty(new ThrottleJobProperty(1, 1, Arrays.asList(alpha), false, THROTTLE_OPTION_CATEGORY, ThrottleMatrixProjectOptions.DEFAULT, false)); FreeStyleProject p3 = createFreeStyleProject("p3"); - p3.addProperty(new ThrottleJobProperty(1, 1, Arrays.asList(alpha, beta), true, THROTTLE_OPTION_CATEGORY, ThrottleMatrixProjectOptions.DEFAULT)); + p3.addProperty(new ThrottleJobProperty(1, 1, Arrays.asList(alpha, beta), true, THROTTLE_OPTION_CATEGORY, ThrottleMatrixProjectOptions.DEFAULT, false)); FreeStyleProject p4 = createFreeStyleProject("p4"); - p4.addProperty(new ThrottleJobProperty(1, 1, Arrays.asList(beta, gamma), true, THROTTLE_OPTION_CATEGORY, ThrottleMatrixProjectOptions.DEFAULT)); + p4.addProperty(new ThrottleJobProperty(1, 1, Arrays.asList(beta, gamma), true, THROTTLE_OPTION_CATEGORY, ThrottleMatrixProjectOptions.DEFAULT, false)); // TODO when core dep ≥1.480.3, add cloudbees-folder as a test dependency so we can check jobs inside folders assertProjects(alpha, p3); assertProjects(beta, p3, p4);