Skip to content

Commit 1e0c878

Browse files
committed
JENKINS-12092 Block category by other categories
1 parent 880acd2 commit 1e0c878

File tree

5 files changed

+68
-3
lines changed

5 files changed

+68
-3
lines changed

src/main/java/hudson/plugins/throttleconcurrents/ThrottleJobProperty.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,21 @@
1717
import hudson.matrix.MatrixProject;
1818

1919
import java.util.ArrayList;
20+
import java.util.Arrays;
2021
import java.util.Collection;
2122
import java.util.Collections;
2223
import java.util.HashMap;
2324
import java.util.List;
2425
import java.util.Map;
2526
import java.util.WeakHashMap;
27+
2628
import javax.annotation.CheckForNull;
2729
import javax.annotation.Nonnull;
28-
import jenkins.model.Jenkins;
2930

31+
import jenkins.model.Jenkins;
3032
import net.sf.json.JSONObject;
3133

34+
import org.apache.commons.lang.StringUtils;
3235
import org.kohsuke.stapler.DataBoundConstructor;
3336
import org.kohsuke.stapler.QueryParameter;
3437
import org.kohsuke.stapler.StaplerRequest;
@@ -319,20 +322,34 @@ public static final class ThrottleCategory extends AbstractDescribableImpl<Throt
319322
private Integer maxConcurrentPerNode;
320323
private Integer maxConcurrentTotal;
321324
private String categoryName;
325+
private String blockingCategories;
326+
private List<String> blockingCategoriesList = new ArrayList<String>();
322327
private List<NodeLabeledPair> nodeLabeledPairs;
323328

324329
@DataBoundConstructor
325330
public ThrottleCategory(String categoryName,
326331
Integer maxConcurrentPerNode,
327332
Integer maxConcurrentTotal,
333+
String blockingCategories,
328334
List<NodeLabeledPair> nodeLabeledPairs) {
329335
this.maxConcurrentPerNode = maxConcurrentPerNode == null ? 0 : maxConcurrentPerNode;
330336
this.maxConcurrentTotal = maxConcurrentTotal == null ? 0 : maxConcurrentTotal;
331337
this.categoryName = categoryName;
338+
this.blockingCategories = blockingCategories;
332339
this.nodeLabeledPairs =
333340
nodeLabeledPairs == null ? new ArrayList<NodeLabeledPair>() : nodeLabeledPairs;
341+
342+
convertCategoriesToList(blockingCategories);
334343
}
335344

345+
private void convertCategoriesToList(String categoriesString) {
346+
String[] catArray = StringUtils.split(categoriesString, ',');
347+
catArray = StringUtils.stripAll(catArray);
348+
if (catArray != null) {
349+
Collections.addAll(blockingCategoriesList, catArray);
350+
}
351+
}
352+
336353
public Integer getMaxConcurrentPerNode() {
337354
if (maxConcurrentPerNode == null)
338355
maxConcurrentPerNode = 0;
@@ -351,6 +368,14 @@ public String getCategoryName() {
351368
return categoryName;
352369
}
353370

371+
public String getBlockingCategories() {
372+
return blockingCategories;
373+
}
374+
375+
public List<String> getBlockingCategoriesList() {
376+
return blockingCategoriesList;
377+
}
378+
354379
public List<NodeLabeledPair> getNodeLabeledPairs() {
355380
if (nodeLabeledPairs == null)
356381
nodeLabeledPairs = new ArrayList<NodeLabeledPair>();

src/main/java/hudson/plugins/throttleconcurrents/ThrottleQueueTaskDispatcher.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package hudson.plugins.throttleconcurrents;
22

3+
34
import hudson.Extension;
45
import hudson.matrix.MatrixConfiguration;
56
import hudson.matrix.MatrixProject;
@@ -13,14 +14,18 @@
1314
import hudson.model.labels.LabelAtom;
1415
import hudson.model.queue.CauseOfBlockage;
1516
import hudson.model.queue.QueueTaskDispatcher;
17+
import hudson.plugins.throttleconcurrents.ThrottleJobProperty.ThrottleCategory;
1618

1719
import java.util.List;
1820
import java.util.Set;
1921
import java.util.logging.Level;
2022
import java.util.logging.Logger;
23+
2124
import javax.annotation.CheckForNull;
2225
import javax.annotation.Nonnull;
2326

27+
import org.apache.commons.lang.StringUtils;
28+
2429
@Extension
2530
public class ThrottleQueueTaskDispatcher extends QueueTaskDispatcher {
2631

@@ -153,6 +158,11 @@ else if (tjp.getThrottleOption().equals("category")) {
153158

154159
// Double check category itself isn't null
155160
if (category != null) {
161+
// Check if this job is blocked by category
162+
if (isBlockedByCategories(category.getBlockingCategoriesList())) {
163+
return CauseOfBlockage.fromMessage(Messages._ThrottleQueueTaskDispatcher_BlockedByCategory());
164+
}
165+
156166
if (category.getMaxConcurrentTotal().intValue() > 0) {
157167
int maxConcurrentTotal = category.getMaxConcurrentTotal().intValue();
158168
int totalRunCount = 0;
@@ -178,6 +188,32 @@ else if (tjp.getThrottleOption().equals("category")) {
178188
return null;
179189
}
180190

191+
private boolean isBlockedByCategories(List<String> categoryNames) {
192+
for (String catName : categoryNames) {
193+
if (areProjectsInCategoryBuilding(catName)) {
194+
return true;
195+
}
196+
}
197+
return false;
198+
}
199+
200+
private boolean areProjectsInCategoryBuilding(String categoryName) {
201+
List<AbstractProject<?, ?>> projectsInCategory = ThrottleJobProperty.getCategoryProjects(categoryName);
202+
for (AbstractProject<?, ?> project : projectsInCategory) {
203+
if (isProjectBuilding(project)) {
204+
return true;
205+
}
206+
}
207+
return false;
208+
}
209+
210+
private boolean isProjectBuilding(AbstractProject<?, ?> project) {
211+
if (project.isBuilding() || project.isInQueue()) {
212+
return true;
213+
}
214+
return false;
215+
}
216+
181217
@CheckForNull
182218
private ThrottleJobProperty getThrottleJobProperty(Task task) {
183219
if (task instanceof AbstractProject) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
ThrottleQueueTaskDispatcher.MaxCapacityOnNode=Already running {0} builds on node
22
ThrottleQueueTaskDispatcher.MaxCapacityTotal=Already running {0} builds across all nodes
33
ThrottleQueueTaskDispatcher.BuildPending=A build is pending launch
4+
ThrottleQueueTaskDispatcher.BlockedByCategory=Build is blocked by jobs in another category
45

56
ThrottleMatrixProjectOptions.DisplayName=Additional options for Matrix projects

src/main/resources/hudson/plugins/throttleconcurrents/ThrottleJobProperty/global.jelly

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
<f:entry title="${%Maximum Concurrent Builds Per Node}" field="maxConcurrentPerNode">
1414
<f:textbox />
1515
</f:entry>
16+
<f:entry title="${%Blocking Categories}" field="blockingCategories">
17+
<f:textbox />
18+
</f:entry>
1619
</table>
1720
<f:repeatable field="nodeLabeledPairs" add="${%Add Maximum Per Labeled Node}" minimum="0" header="${%Maximum Per Labeled Node}">
1821
<table width="100%">

src/test/java/hudson/plugins/throttleconcurrents/ThrottleCategoryTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class ThrottleCategoryTest
3636
public void shouldGetEmptyNodeLabeledPairsListUponInitialNull()
3737
{
3838
ThrottleJobProperty.ThrottleCategory category =
39-
new ThrottleJobProperty.ThrottleCategory(testCategoryName, 0, 0, null);
39+
new ThrottleJobProperty.ThrottleCategory(testCategoryName, 0, 0, null, null);
4040
assertTrue("nodeLabeledPairs shall be empty", category.getNodeLabeledPairs().isEmpty());
4141
}
4242

@@ -47,7 +47,7 @@ public void shouldGetNonEmptyNodeLabeledPairsListThatWasSet()
4747
Integer expectedMax = new Integer(1);
4848

4949
ThrottleJobProperty.ThrottleCategory category =
50-
new ThrottleJobProperty.ThrottleCategory(testCategoryName, 0, 0, null);
50+
new ThrottleJobProperty.ThrottleCategory(testCategoryName, 0, 0, "", null);
5151
List<ThrottleJobProperty.NodeLabeledPair> nodeLabeledPairs = category.getNodeLabeledPairs();
5252
nodeLabeledPairs.add(new ThrottleJobProperty.NodeLabeledPair(expectedLabel, expectedMax));
5353

0 commit comments

Comments
 (0)