-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid saving nextBuildNumber
while loading Job
#9778
Conversation
// starting 1.28, we store nextBuildNumber in a separate file. | ||
// but old Hudson didn't do it, so if the file doesn't exist, | ||
// assume that nextBuildNumber was read from config.xml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment about Hudson 1.27 did not seem particularly helpful at this point!
try { | ||
synchronized (this) { | ||
this.nextBuildNumber = Integer.parseInt(f.readTrim()); | ||
} | ||
} catch (NumberFormatException e) { | ||
LOGGER.log(Level.WARNING, "Corruption in {0}: {1}", new Object[] {f, e}); | ||
//noinspection StatementWithEmptyBody | ||
if (this instanceof LazyBuildMixIn.LazyLoadingJob) { | ||
// allow LazyBuildMixIn.onLoad to fix it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It no longer does so, so simplify and use the same logic for all Job
types. (In practice all jobs in common usage use LazyBuildMixIn
.)
} | ||
} else { | ||
// From the old Hudson, or doCreateItem. Create this file now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact doCreateItem
calls onCreatedFromScratch
, which did not create this file, so that was misleading.
} else if (nextBuildNumber == 0) { | ||
nextBuildNumber = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can happen if the file was absent when a job which had never been built was loaded from disk. The field initializer
protected transient volatile int nextBuildNumber = 1; |
@@ -109,8 +109,8 @@ public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOExcep | |||
int max = _builds.maxNumberOnDisk(); | |||
int next = asJob().getNextBuildNumber(); | |||
if (next <= max) { | |||
LOGGER.log(Level.WARNING, "JENKINS-27530: improper nextBuildNumber {0} detected in {1} with highest build number {2}; adjusting", new Object[] {next, asJob(), max}); | |||
asJob().updateNextBuildNumber(max + 1); | |||
LOGGER.log(Level.FINE, "nextBuildNumber {0} detected in {1} with highest build number {2}; adjusting", new Object[] {next, asJob(), max}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compare #2439
LOGGER.log(Level.WARNING, "JENKINS-27530: improper nextBuildNumber {0} detected in {1} with highest build number {2}; adjusting", new Object[] {next, asJob(), max}); | ||
asJob().updateNextBuildNumber(max + 1); | ||
LOGGER.log(Level.FINE, "nextBuildNumber {0} detected in {1} with highest build number {2}; adjusting", new Object[] {next, asJob(), max}); | ||
asJob().fastUpdateNextBuildNumber(max + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
introduced in #9019
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/label ready-for-merge
This PR is now ready for merge, after ~24 hours, we will merge it if there's no negative feedback.
Thanks!
I spent a while looking into a semi-reproducible test failure affecting CloudBees CI running in high availability mode. The scenario involves a job being created and then a build immediately being scheduled;
config.xml
is created and thennextBuildNumber
is created shortly thereafter. If another process is loading the job in between, it can attempt to write outnextBuildNumber
itself, despite not actually running any build of the job. The details are probably not relevant to OSS Jenkins users but the essential guideline is that you should not be writing files to disk just because you are loading some configuration from disk, at least not without a good reason. The file should be written only if and when a build is scheduled; its absence should be treated as an implicit value of 1. (lastBuildNumber
with an implicit value of 0 would perhaps have been more intuitive.)I did keep the clause which recomputes and writes out
nextBuildNumber
in case the file existed but was corrupt (not parsable as an integer), since otherwise you might be printing an error on every Jenkins startup, if the job is never built again.Testing done
Seems to resolve a timing-dependent test failure observed in CloudBees CI proprietary code.
Proposed changelog entries
N/A, likely not interesting.
Before the changes are marked as
ready-for-merge
:Maintainer checklist