Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #115 from stephenc/jenkins-44335
[FIXED JENKINS-44335] Add user boosting capability to rate limit property
  • Loading branch information
stephenc committed Dec 4, 2017
2 parents 5f1a1af + ed6169c commit 4200a1d
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 16 deletions.
84 changes: 80 additions & 4 deletions src/main/java/jenkins/branch/RateLimitBranchProperty.java
Expand Up @@ -25,6 +25,7 @@

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.model.Cause;
import hudson.model.Job;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
Expand Down Expand Up @@ -91,18 +92,37 @@ private static Map<String, Long> createDurations() {
* The maximum builds within the duration.
*/
private final int count;
/**
* If {@code true} then user cause builds will be allowed to exceed the throttle.
*
* @since TODO
*/
private final boolean userBoost;

/**
* Constructor for stapler.
*
* @param count the maximum builds within the duration.
* @param durationName the name of the duration.
*/
@Deprecated
public RateLimitBranchProperty(int count, String durationName) {
this(count, durationName, false);
}

/**
* Constructor for stapler.
*
* @param count the maximum builds within the duration.
* @param durationName the name of the duration.
* @param userBoost {@code true} to allow user submitted jobs to ignore the rate limits.
*/
@DataBoundConstructor
@SuppressWarnings("unused") // instantiated by stapler
public RateLimitBranchProperty(int count, String durationName) {
public RateLimitBranchProperty(int count, String durationName, boolean userBoost) {
this.count = Math.min(Math.max(1, count), 1000);
this.durationName = durationName == null || !DURATIONS.containsKey(durationName) ? "hour" : durationName;
this.userBoost = userBoost;
}

/**
Expand All @@ -125,6 +145,15 @@ public String getDurationName() {
return durationName;
}

/**
* Gets the user boost setting.
*
* @return the user boost setting.
*/
public boolean isUserBoost() {
return userBoost;
}

/**
* {@inheritDoc}
*/
Expand All @@ -140,7 +169,7 @@ public <P extends Job<P, B>, B extends Run<P, B>> JobDecorator<P, B> jobDecorato
public List<JobProperty<? super P>> jobProperties(
@NonNull List<JobProperty<? super P>> properties) {
List<JobProperty<? super P>> result = asArrayList(properties);
result.add(new JobPropertyImpl(count == 0 ? null : new Throttle(count, durationName)));
result.add(new JobPropertyImpl(count == 0 ? null : new Throttle(count, durationName, userBoost)));
return result;
}
};
Expand Down Expand Up @@ -199,17 +228,25 @@ public static class Throttle {
* The maximum builds within the duration.
*/
private final int count;
/**
* If {@code true} then user cause builds will be allowed to exceed the throttle.
*
* @since TODO
*/
private final boolean userBoost;

/**
* Constructor for stapler.
*
* @param count the maximum builds within the duration.
* @param durationName the name of the duration.
* @param userBoost if {@code true} then user submitted builds will skip the queue.
*/
@DataBoundConstructor
public Throttle(int count, String durationName) {
public Throttle(int count, String durationName, boolean userBoost) {
this.count = Math.min(Math.max(0, count), 1000);
this.durationName = durationName == null || !DURATIONS.containsKey(durationName) ? "hour" : durationName;
this.userBoost = userBoost;
}

/**
Expand All @@ -230,6 +267,14 @@ public String getDurationName() {
return durationName;
}

/**
* Gets the user boost setting.
*
* @return the user boost setting.
*/
public boolean isUserBoost() {
return userBoost;
}
}

public static class JobPropertyImpl extends JobProperty<Job<?, ?>> {
Expand All @@ -243,6 +288,12 @@ public static class JobPropertyImpl extends JobProperty<Job<?, ?>> {
* The maximum builds within the duration.
*/
private final int count;
/**
* If {@code true} then user cause builds will be allowed to exceed the throttle.
*
* @since TODO
*/
private final boolean userBoost;

/**
* The milliseconds of the duration.
Expand All @@ -264,6 +315,7 @@ public JobPropertyImpl(Throttle throttle) {
this.throttle = throttle;
this.count = throttle == null ? 0 : Math.min(Math.max(0, throttle.getCount()), 1000);
this.durationName = throttle == null ? "hour" : throttle.getDurationName();
this.userBoost = throttle == null ? true : throttle.isUserBoost();
}

/**
Expand All @@ -284,6 +336,15 @@ public String getDurationName() {
return durationName;
}

/**
* Gets the user boost setting.
*
* @return the user boost setting.
*/
public boolean isUserBoost() {
return userBoost;
}

/**
* Gets the duration.
*
Expand All @@ -309,7 +370,7 @@ public Throttle getThrottle() {
return null;
}
if (throttle == null) {
throttle = new Throttle(count, durationName);
throttle = new Throttle(count, durationName, userBoost);
}
return throttle;
}
Expand Down Expand Up @@ -418,6 +479,21 @@ public CauseOfBlockage canRun(Queue.Item item) {
Job<?, ?> job = (Job) item.task;
JobPropertyImpl property = job.getProperty(JobPropertyImpl.class);
if (property != null) {
if (property.isUserBoost()) {
for (Cause cause : item.getCauses()) {
if (cause instanceof Cause.UserIdCause || cause instanceof Cause.UserCause) {
LOGGER.log(Level.FINER, "{0} has a rate limit of {1} builds per {2} "
+ "but user submitted and boost enabled",
new Object[]{
job.getFullName(),
property.getCount(),
property.getDurationName()
}
);
return null;
}
}
}
LOGGER.log(Level.FINER, "{0} has a rate limit of {1} builds per {2}",
new Object[]{
job.getFullName(),
Expand Down
Expand Up @@ -30,5 +30,8 @@
<f:entry title="${%Time period}" field="durationName">
<f:select/>
</f:entry>
<f:entry field="userBoost">
<f:checkbox title="${%Allow user triggered builds to skip the rate limit}"/>
</f:entry>
</f:optionalBlock>
</j:jelly>
</j:jelly>
@@ -0,0 +1,5 @@
<div>
Enable this option to permit user triggered builds to skip the rate limit.
Note that user triggered builds will still consume the rate limit for all builds, they just
will not be subject to the limit.
</div>
Expand Up @@ -29,4 +29,7 @@
<f:entry title="${%Time period}" field="durationName">
<f:select/>
</f:entry>
</j:jelly>
<f:entry field="userBoost">
<f:checkbox title="${%Allow user triggered builds to skip the rate limit}"/>
</f:entry>
</j:jelly>
@@ -0,0 +1,5 @@
<div>
Enable this option to permit user triggered builds to skip the rate limit.
Note that user triggered builds will still consume the rate limit for all builds, they just
will not be subject to the limit.
</div>

0 comments on commit 4200a1d

Please sign in to comment.