-
Improvement
-
Resolution: Fixed
-
Major
-
-
jenkins 2.145, workflow-durable-task-step 2.29
The default LoadBalancer, CONSISTENT_HASH, tries to reassign the same node to repeated builds of a given project, so as to reuse workspaces whenever possible. However to identify the project it uses Queue.Task.getFullDisplayName as seen here. For an AbstractProject this works OK, since this method will be implemented in AbstractItem and remains pretty stable across builds—at least so long as you do not rename the project or a containing folder!
For Pipeline builds it does not work at all, since the PlaceholderTask implementation encodes the build number. Thus, the key to the load balancer changes with every build, and there is no affinity.
Queue.Task.getName used to be documented to serve this function but it is no different in the case of PlaceholderTask, and worse in the case of AbstractProject (since it throws out the project path, though it is more resilient to display name changes). getUrl sounds like a better key, but again for PlaceholderTask it is intentionally sensitive to the Run's build number, so that you can click on a queue item and see which Pipeline build it was coming from, not just which job. And Task has no getFullName, oddly.
The load balancer could perhaps call getOwnerTask before using getFullDisplayName. This would have no effect on AbstractProject, but for PlaceholderTask would let it delegate to WorkflowJob, so the affinity would work tolerably well, at least so long as your build has only a single node block—for multiple blocks it will tend to break down. There is also some risk of mangling affinity calculations for other SubTask implementations with different needs.
What we really need is an extended API for a Task which can specify a dedicated affinity key directly, not overloaded by UI elements. AbstractProject should implement it to return getFullName. PlaceholderTask could implement this at a minimum to return WorkflowJob.getFullName, but could also do better by looking up an enclosing label for the node as in JENKINS-26132 and concatenating that with the job name, so that for example a script like
stage('Build') { node('unix') { git '.../main-sources' sh './build.sh' stash 'binaries' } } stage('Test') { parallel unixTests: { node('unix') { git '.../tests' unstash 'binaries' sh './test.sh' } }, windowsTests: { node('windows') { git '.../tests' unstash 'binaries' bat 'test.bat' } } } stage('Deploy') { node('unix') { git '.../tools' unstash 'binaries' sh './deploy.sh' } }
would result in four affinity keys being used: prjname#Build, prhname#unixTests, prjname#windowsTests, prjname#Deploy, each resulting in distinct persistent workspaces.
- causes
-
JENKINS-57805 Exception thrown from ExecutorStepExecution.PlaceHolderTask.getAffinityKey breaks Queue maintenance
- Resolved
-
JENKINS-60389 Queue.maintain blocked by WorkflowJob.getBuildByNumber via getAffinityKey
- Resolved
- is blocking
-
JENKINS-45553 Parallel pipeline execution scales poorly
- Closed
- is duplicated by
-
JENKINS-51100 Jenkins multibranch pipeline keeps scheduling jobs to new nodes
- Resolved
-
JENKINS-52529 node() step shall try to reuse node from last run
- Resolved
- is related to
-
JENKINS-26132 Executor should show the current stage the flow run is in
- Resolved
- relates to
-
JENKINS-48348 If task can be run only on master, use shortcut
- Resolved
- links to