From c8c8fa5a29ac7c4e724b38756932c26aaf3cdece Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Tue, 8 Oct 2024 15:42:24 -0400 Subject: [PATCH 1/2] `Job.BuildNumberAssigner` --- core/src/main/java/hudson/model/Job.java | 48 +++++++++++++++++++++--- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index e4d54d44b375..36bd9407e7d4 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -34,6 +34,7 @@ import hudson.BulkChange; import hudson.EnvVars; import hudson.Extension; +import hudson.ExtensionList; import hudson.ExtensionPoint; import hudson.FeedAdapter; import hudson.PermalinkList; @@ -346,12 +347,49 @@ public boolean isKeepDependencies() { } /** - * Allocates a new buildCommand number. + * Allocates a new build number. + * @see BuildNumberAssigner */ - public synchronized int assignBuildNumber() throws IOException { - int r = nextBuildNumber++; - saveNextBuildNumber(); - return r; + public int assignBuildNumber() throws IOException { + var bna = ExtensionList.lookupFirst(BuildNumberAssigner.class).assignBuildNumber(this); + if (bna.needsSave) { + saveNextBuildNumber(); + } + return bna.assignedNumber; + } + + /** + * Alternate strategy for assigning build numbers. + * @see #assignBuildNumber() + */ + @Restricted(Beta.class) + public interface BuildNumberAssigner extends ExtensionPoint { + /** + * Strategy outcome. + * @param assignedNumber the return value for {@link #assignBuildNumber()} + * @param needsSave whether {@link #saveNextBuildNumber} should be called afterwards + */ + record BuildNumberAssignment(int assignedNumber, boolean needsSave) {}; + + /** + * Assign a unique number for a new build of a given job. + * @see #getNextBuildNumber + * @see #fastUpdateNextBuildNumber + */ + BuildNumberAssignment assignBuildNumber(Job job) throws IOException; + } + + @Restricted(DoNotUse.class) + @Extension(ordinal = -1000) + public static final class DefaultBuildNumberAssigner implements BuildNumberAssigner { + @Override + public BuildNumberAssignment assignBuildNumber(Job job) throws IOException { + synchronized (job) { + int r = job.nextBuildNumber++; + job.saveNextBuildNumber(); + return new BuildNumberAssignment(r, false); + } + } } /** From b73a0c5baefdf63e9f153ed137f7ceb66d3562eb Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Wed, 9 Oct 2024 10:21:32 -0400 Subject: [PATCH 2/2] Clearer API for `saveNextBuildNumber` https://github.com/jenkinsci/jenkins/pull/9846#discussion_r1792991572 --- core/src/main/java/hudson/model/Job.java | 29 +++++++++--------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index 36bd9407e7d4..a393e33c9a6b 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -351,43 +351,36 @@ public boolean isKeepDependencies() { * @see BuildNumberAssigner */ public int assignBuildNumber() throws IOException { - var bna = ExtensionList.lookupFirst(BuildNumberAssigner.class).assignBuildNumber(this); - if (bna.needsSave) { - saveNextBuildNumber(); - } - return bna.assignedNumber; + return ExtensionList.lookupFirst(BuildNumberAssigner.class).assignBuildNumber(this, this::saveNextBuildNumber); } /** * Alternate strategy for assigning build numbers. - * @see #assignBuildNumber() */ @Restricted(Beta.class) public interface BuildNumberAssigner extends ExtensionPoint { /** - * Strategy outcome. - * @param assignedNumber the return value for {@link #assignBuildNumber()} - * @param needsSave whether {@link #saveNextBuildNumber} should be called afterwards + * Implementation of {@link Job#assignBuildNumber}. */ - record BuildNumberAssignment(int assignedNumber, boolean needsSave) {}; - + int assignBuildNumber(Job job, SaveNextBuildNumber saveNextBuildNumber) throws IOException; /** - * Assign a unique number for a new build of a given job. - * @see #getNextBuildNumber - * @see #fastUpdateNextBuildNumber + * Provides an externally accessible alias for {@link Job#saveNextBuildNumber}, which is {@code protected}. + * ({@link #getNextBuildNumber} and {@link #fastUpdateNextBuildNumber} are already accessible.) */ - BuildNumberAssignment assignBuildNumber(Job job) throws IOException; + interface SaveNextBuildNumber { + void call() throws IOException; + } } @Restricted(DoNotUse.class) @Extension(ordinal = -1000) public static final class DefaultBuildNumberAssigner implements BuildNumberAssigner { @Override - public BuildNumberAssignment assignBuildNumber(Job job) throws IOException { + public int assignBuildNumber(Job job, SaveNextBuildNumber saveNextBuildNumber) throws IOException { synchronized (job) { int r = job.nextBuildNumber++; - job.saveNextBuildNumber(); - return new BuildNumberAssignment(r, false); + saveNextBuildNumber.call(); + return r; } } }