Cancel jobs behind a failed change.

Jobs behind a failed change will need to be rerun so cancel them
to free up resources at the front of the change queue. When a change
at the front of the queue fails it is dequeued and all the jobs behind
it are rerun. When a change in the middle of the queue fails all the
jobs behind it are cancelled. Then the jobs will be rerun when a
change at the front of the queue is dequeued for failure (which may
end up being the change that caused the initial cancellation, or it
may be a change further up in the queue).

Change-Id: Ic0ebe15ec1a8d3a21ff04a6769243729683807ed
This commit is contained in:
Clark Boylan 2012-07-12 16:44:46 -07:00
parent 6173fb3949
commit 826ef9e039
2 changed files with 25 additions and 3 deletions

View File

@ -449,6 +449,14 @@ class Change(object):
return False
return True
def didAnyJobFail(self):
tree = self.project.getJobTreeForQueue(self.queue_name)
for job in self._filterJobs(tree.getJobs()):
build = self.current_build_set.getBuild(job.name)
if build and build.result == 'FAILURE':
return True
return False
def delete(self):
if self.change_behind:
self.change_behind.change_ahead = None

View File

@ -609,10 +609,11 @@ for change %s:" % (job, change))
change.change_behind, change))
self.launchJobs(change.change_behind)
def cancelJobs(self, change):
def cancelJobs(self, change, prime=True):
self.log.debug("Cancel jobs for change %s" % change)
to_remove = []
change.resetAllBuilds()
if prime:
change.resetAllBuilds()
for build, build_change in self.building_jobs.items():
if build_change == change:
self.log.debug("Found build %s for change %s to cancel" % (
@ -630,7 +631,20 @@ for change %s" % (build, change))
if change.change_behind:
self.log.debug("Canceling jobs for change %s, \
behind change %s" % (change.change_behind, change))
self.cancelJobs(change.change_behind)
self.cancelJobs(change.change_behind, prime=prime)
def onBuildCompleted(self, build):
change = self.building_jobs.get(build)
if not super(DependentQueueManager, self).onBuildCompleted(build):
return False
if change and change.didAnyJobFail():
# This or some other build failed. All changes behind this change
# will need to be retested. To free up resources cancel the builds
# behind this one as they will be rerun anyways.
self.cancelJobs(change.change_behind, prime=False)
self.log.debug("Canceling builds behind change: %s due to"
" failure." % change)
return True
def possiblyReportChange(self, change):
self.log.debug("Possibly reporting change %s" % change)