diff --git a/src/main/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep.java b/src/main/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep.java
index 76a78020..95b9db8b 100644
--- a/src/main/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep.java
+++ b/src/main/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep.java
@@ -40,9 +40,10 @@
public final class WaitForConditionStep extends Step {
static final long MIN_RECURRENCE_PERIOD = 250; // ¼s
- static final long MAX_RECURRENCE_PERIOD = 15000; // ¼min
+ static final long DEFAULT_MAX_RECURRENCE_PERIOD = 15000; // ¼min
private long initialRecurrencePeriod = MIN_RECURRENCE_PERIOD;
+ private long maxRecurrencePeriod = DEFAULT_MAX_RECURRENCE_PERIOD;
private boolean quiet = false;
@DataBoundConstructor
@@ -50,14 +51,22 @@ public WaitForConditionStep() {}
@DataBoundSetter
public void setInitialRecurrencePeriod(long initialRecurrencePeriod) {
- this.initialRecurrencePeriod =
- Math.max(MIN_RECURRENCE_PERIOD, Math.min(initialRecurrencePeriod, MAX_RECURRENCE_PERIOD));
+ this.initialRecurrencePeriod = Math.max(MIN_RECURRENCE_PERIOD, initialRecurrencePeriod);
}
public long getInitialRecurrencePeriod() {
return initialRecurrencePeriod;
}
+ @DataBoundSetter
+ public void setMaxRecurrencePeriod(long maxRecurrencePeriod) {
+ this.maxRecurrencePeriod = maxRecurrencePeriod;
+ }
+
+ public long getMaxRecurrencePeriod(long maxRecurrencePeriod) {
+ return maxRecurrencePeriod;
+ }
+
@DataBoundSetter
public void setQuiet(boolean quiet) {
this.quiet = quiet;
@@ -69,7 +78,11 @@ public boolean getQuiet() {
@Override
public StepExecution start(StepContext context) throws Exception {
- return new Execution(context, initialRecurrencePeriod, this.quiet);
+ if (maxRecurrencePeriod < initialRecurrencePeriod) {
+ throw new IllegalStateException("The initial recurrance period must not be greater than the maximum.");
+ }
+ long initial = Math.max(MIN_RECURRENCE_PERIOD, Math.min(initialRecurrencePeriod, maxRecurrencePeriod));
+ return new Execution(context, initial, maxRecurrencePeriod, this.quiet);
}
public static final class Execution extends AbstractStepExecutionImpl {
@@ -85,12 +98,14 @@ public static final class Execution extends AbstractStepExecutionImpl {
private static final float RECURRENCE_PERIOD_BACKOFF = 1.2f;
private long initialRecurrencePeriod;
+ private long maxRecurrencePeriod;
long recurrencePeriod;
private final boolean quiet;
- Execution(StepContext context, long initialRecurrencePeriod, boolean quiet) {
+ Execution(StepContext context, long initialRecurrencePeriod, long maxRecurrencePeriod, boolean quiet) {
super(context);
this.initialRecurrencePeriod = initialRecurrencePeriod;
+ this.maxRecurrencePeriod = maxRecurrencePeriod;
recurrencePeriod = initialRecurrencePeriod;
this.quiet = quiet;
}
@@ -100,6 +115,9 @@ private Object readResolve() {
if (initialRecurrencePeriod == 0) {
initialRecurrencePeriod = MIN_RECURRENCE_PERIOD;
}
+ if (maxRecurrencePeriod == 0) {
+ maxRecurrencePeriod = DEFAULT_MAX_RECURRENCE_PERIOD;
+ }
return this;
}
@@ -162,7 +180,7 @@ private void retry(StepContext perBodyContext) {
},
recurrencePeriod,
TimeUnit.MILLISECONDS);
- recurrencePeriod = Math.min((long) (recurrencePeriod * RECURRENCE_PERIOD_BACKOFF), MAX_RECURRENCE_PERIOD);
+ recurrencePeriod = Math.min((long) (recurrencePeriod * RECURRENCE_PERIOD_BACKOFF), maxRecurrencePeriod);
}
@Override
diff --git a/src/main/resources/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep/config.jelly b/src/main/resources/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep/config.jelly
index 4a4ec2c0..4ed94dfe 100644
--- a/src/main/resources/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep/config.jelly
+++ b/src/main/resources/org/jenkinsci/plugins/workflow/steps/WaitForConditionStep/config.jelly
@@ -28,6 +28,9 @@ THE SOFTWARE.
+
+
+
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStepTest.java
index e28a7962..163803a3 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStepTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/WaitForConditionStepTest.java
@@ -92,6 +92,27 @@ void initialRecurrence() throws Throwable {
});
}
+ @Test
+ void maxRecurrence() throws Throwable {
+ sessions.then(j -> {
+ WorkflowJob p = j.createProject(WorkflowJob.class, "p");
+ p.setDefinition(new CpsFlowDefinition(
+ "waitUntil(initialRecurrencePeriod: 250, maxRecurrencePeriod: 255) {semaphore 'wait'}; semaphore 'waited'", true));
+ WorkflowRun b = p.scheduleBuild2(0).waitForStart();
+ SemaphoreStep.waitForStart("wait/1", b);
+ SemaphoreStep.success("wait/1", false);
+ SemaphoreStep.waitForStart("wait/2", b);
+ SemaphoreStep.success("wait/2", false);
+ SemaphoreStep.waitForStart("wait/3", b);
+ SemaphoreStep.success("wait/3", true);
+ SemaphoreStep.waitForStart("waited/1", b);
+ SemaphoreStep.success("waited/1", null);
+ WorkflowRun run = j.assertBuildStatusSuccess(j.waitForCompletion(b));
+ j.assertLogContains("Will try again after " + Util.getTimeSpanString(250), run);
+ j.assertLogContains("Will try again after " + Util.getTimeSpanString(255), run);
+ });
+ }
+
@Test
void failure() throws Throwable {
sessions.then(j -> {