From fe52887da2fc8810e8a5bffcdda95c6698cef7be Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Mon, 29 May 2023 11:00:42 -0400 Subject: [PATCH] Lazy-load-friendly `Job.getEstimatedDurationCandidates` (#7998) --- .../java/hudson/model/AbstractProject.java | 5 ++++ core/src/main/java/hudson/model/Job.java | 1 + .../jenkins/model/lazy/LazyBuildMixIn.java | 26 +++++++++++++++++++ test/src/test/java/hudson/model/JobTest.java | 1 - .../test/java/hudson/model/RunMapTest.java | 2 -- .../model/lazy/LazyBuildMixInTest.java | 16 ++++++++++++ 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 809c215a61..099d0d190d 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -953,6 +953,11 @@ public abstract class AbstractProject

, R extends return buildMixIn.getNearestOldBuild(n); } + @Override + protected List getEstimatedDurationCandidates() { + return buildMixIn.getEstimatedDurationCandidates(); + } + /** * Type token for the corresponding build type. * The build class must have two constructors: diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index dd9d88ff25..6c3596a1b0 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -1013,6 +1013,7 @@ public abstract class Job, RunT extends Run getEstimatedDurationCandidates() { List candidates = new ArrayList<>(3); diff --git a/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java b/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java index e6e2b51906..08950c398a 100644 --- a/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java +++ b/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java @@ -34,6 +34,7 @@ import hudson.model.Item; import hudson.model.ItemGroup; import hudson.model.Job; import hudson.model.Queue; +import hudson.model.Result; import hudson.model.Run; import hudson.model.RunMap; import hudson.model.listeners.ItemListener; @@ -44,6 +45,8 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; @@ -265,6 +268,29 @@ public abstract class LazyBuildMixIn & Queue.Task & return builds.search(n, AbstractLazyLoadRunMap.Direction.DESC); } + /** + * Suitable for {@link Job#getEstimatedDurationCandidates}. + * @since TODO + */ + public List getEstimatedDurationCandidates() { + var loadedBuilds = builds.getLoadedBuilds().values(); // reverse chronological order + List candidates = new ArrayList<>(3); + for (Result threshold : List.of(Result.UNSTABLE, Result.FAILURE)) { + for (RunT build : loadedBuilds) { + if (!build.isBuilding()) { + Result result = build.getResult(); + if (result != null && result.isBetterOrEqualTo(threshold)) { + candidates.add(build); + if (candidates.size() == 3) { + return candidates; + } + } + } + } + } + return candidates; + } + /** * Suitable for {@link Job#createHistoryWidget}. */ diff --git a/test/src/test/java/hudson/model/JobTest.java b/test/src/test/java/hudson/model/JobTest.java index 22d3200c8a..7cd425ddbe 100644 --- a/test/src/test/java/hudson/model/JobTest.java +++ b/test/src/test/java/hudson/model/JobTest.java @@ -302,7 +302,6 @@ public class JobTest { @Issue("JENKINS-16023") @Test public void getLastFailedBuild() throws Exception { final FreeStyleProject p = j.createFreeStyleProject(); - RunLoadCounter.prepare(p); p.getBuildersList().add(new FailureBuilder()); j.buildAndAssertStatus(Result.FAILURE, p); j.buildAndAssertStatus(Result.FAILURE, p); diff --git a/test/src/test/java/hudson/model/RunMapTest.java b/test/src/test/java/hudson/model/RunMapTest.java index 979453dc11..22d3b9dffa 100644 --- a/test/src/test/java/hudson/model/RunMapTest.java +++ b/test/src/test/java/hudson/model/RunMapTest.java @@ -192,7 +192,6 @@ public class RunMapTest { @Test public void runLoadCounterFirst() throws Exception { FreeStyleProject p = r.createFreeStyleProject(); - RunLoadCounter.prepare(p); for (int i = 0; i < 10; i++) { r.buildAndAssertSuccess(p); } @@ -204,7 +203,6 @@ public class RunMapTest { @Test public void runLoadCounterLimit() throws Exception { FreeStyleProject p = r.createFreeStyleProject(); - RunLoadCounter.prepare(p); for (int i = 0; i < 10; i++) { r.buildAndAssertSuccess(p); } diff --git a/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java b/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java index b95aa83bfd..6b2ef4e6cf 100644 --- a/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java +++ b/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java @@ -36,6 +36,7 @@ import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.RunLoadCounter; import org.jvnet.hudson.test.SleepBuilder; public class LazyBuildMixInTest { @@ -96,4 +97,19 @@ public class LazyBuildMixInTest { assertSame(b2, b1.getNextBuild()); r.assertBuildStatusSuccess(r.waitForCompletion(b2)); } + + @Test + public void newBuildsShouldNotLoadOld() throws Throwable { + var p = r.createFreeStyleProject("p"); + for (int i = 0; i < 10; i++) { + r.buildAndAssertSuccess(p); + } + RunLoadCounter.assertMaxLoads(p, /* just lastBuild */ 1, () -> { + for (int i = 0; i < 5; i++) { + r.buildAndAssertSuccess(p); + } + return null; + }); + } + }