After startupUsage of the instance with many jobs1, the setup does not end up @Initializer(after = InitMilestone.COMPLETED) in plugins breaks the COMPLETED milestone initialization logic
The problem is in the following logic Initializer code: {code} // All plugins are loaded** * Indicates that the specified milestone is necessary before executing this initializer. Now we can figure out who depends on who. * * <p> * This has the identical purpose as {@link # requires(PLUGINS_PREPARED).attains}, but it's separated to allow better type-safety * when using {@link InitMilestone} as a requirement(COMPLETED)since enum member definitions need to be constant.add) */ InitMilestone after("Resolving Dependant Plugins Graph", new Executable() { default STARTED; @Override public void run /** * Indicates that this initializer is a necessary step before achieving the specified milestone. * * <p> * This has the identical purpose as {@link #attains(Reactor reactor) throws Exception}. See { resolveDependantPlugins@link #after(); } for why there are two things } * to achieve the same goal. */ InitMilestone before() default COMPLETED; {code}
In this caseIf an initializer overrides <code>after</code> as COMPLETED state logic does not depend on the Job loading state, hence COMPLETED milestone can be achieved before JOB_LOADED we end up in the reactor. It may easily happen situation when Job loading takes MUCH time (<code>before == after == COMPLETED</code>). In such case COMPLETED state gets overridden by JOB_LOADED Jenkins' reactor can never succeed in the canRun() check, and finally we do not invoke "Initialization completed" milestone since the code requires the dependency to be executed. So we get into chicken-and-egg
Sample script for the issue analysis: {code} import hudson.init.InitMilestone; import hudson.util.HttpResponses; import javax.servlet.http.HttpServletResponse;
final Jenkins jenkins = Jenkins.getInstance();
if (jenkins.getInitLevel().compareTo(InitMilestone.COMPLETED) < 0) { println "Error: Jenkins initialization has not reached the COMPLETED state. Current state is ${jenkins.getInitLevel()}" return HttpResponses.status(HttpServletResponse.SC_SERVICE_UNAVAILABLE); } {code}
Proposed changes: * Add injected test, which verifies the startup InitMilestone of Jenkins * Make Jenkins robust against wrong definitions * Finally add support of Initializers after COMPLETED by introducing a transient milestone
Code changed in jenkins User: Oleg Nenashev Path: src/main/java/org/jenkinsci/plugins/extremenotification/MyItemListener.java src/main/java/org/jenkinsci/plugins/extremenotification/ServerStateListener.java src/test/java/org/jenkinsci/plugins/extremenotification/PluginInitializationTest.java http://jenkins-ci.org/commit/extreme-notification-plugin/1814673042bb450de5ec5401bf8096abccc5ff67 Log: [FIXED JENKINS-37780] - The code should not use Initializer(after=InitMilestone.COMPLETED) due to JENKINS-37759