Merge "Handle dependency limit errors more gracefully"

This commit is contained in:
Zuul 2024-03-20 15:05:41 +00:00 committed by Gerrit Code Review
commit 3bcd923a68
6 changed files with 73 additions and 7 deletions

View File

@ -0,0 +1 @@
test

View File

@ -0,0 +1,26 @@
- queue:
name: integrated-topic
allow-circular-dependencies: True
dependencies-by-topic: True
- project:
queue: integrated-topic
check:
jobs:
- project-merge
- project-test1:
dependencies: project-merge
- project-test2:
dependencies: project-merge
gate:
jobs:
- project-merge
- project-test1:
dependencies: project-merge
- project-test2:
dependencies: project-merge
- project-testfile:
dependencies: project-merge
post:
jobs:
- project-post

View File

@ -9,3 +9,4 @@
- org/project
- org/project1
- org/project2
- org/project4

View File

@ -9869,3 +9869,29 @@ class TestMaxDeps(ZuulTestCase):
dict(name='project-test1', result='SUCCESS', changes='1,1 2,1'),
dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
], ordered=False)
def test_max_deps_extended(self):
self.executor_server.hold_jobs_in_build = True
# max_dependencies for the connection is 1, so this is okay
A = self.fake_gerrit.addFakeChange('org/project4', 'master', 'A')
B = self.fake_gerrit.addFakeChange('org/project4', 'master', 'B',
topic='test-topic')
B.setDependsOn(A, 1)
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
self.waitUntilSettled()
# Increase the number of dependencies for B by adding a
# change with the same topic (dependencies-by-topic is enabled).
# With this C should not be enqueued and A is removed.
C = self.fake_gerrit.addFakeChange('org/project4', 'master', 'C',
topic='test-topic')
self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
self.executor_server.hold_jobs_in_build = True
self.executor_server.release()
self.waitUntilSettled()
self.assertHistory([
dict(name='project-merge', result='SUCCESS', changes='1,1 2,1'),
], ordered=False)

View File

@ -50,6 +50,10 @@ class StreamingError(Exception):
pass
class DependencyLimitExceededError(Exception):
pass
# Authentication Exceptions
class AuthTokenException(Exception):

View File

@ -596,8 +596,11 @@ class PipelineManager(metaclass=ABCMeta):
change, self.pipeline)
return False
self.getDependencyGraph(change, dependency_graph, event,
update_deps=True)
try:
self.getDependencyGraph(change, dependency_graph, event,
update_deps=True)
except exceptions.DependencyLimitExceededError:
return False
with self.getChangeQueue(change, event, change_queue) as change_queue:
if not change_queue:
@ -808,9 +811,10 @@ class PipelineManager(metaclass=ABCMeta):
if (self.pipeline.tenant.max_dependencies is not None and
(len(dependency_graph) >
self.pipeline.tenant.max_dependencies)):
log.debug("%sDependency graph for change %s is too large",
indent, change)
raise Exception("Dependency graph is too large")
log.info("%sDependency graph for change %s is too large",
indent, change)
raise exceptions.DependencyLimitExceededError(
"Dependency graph is too large")
node = dependency_graph.setdefault(change, [])
if needed_change not in node:
@ -1619,8 +1623,12 @@ class PipelineManager(metaclass=ABCMeta):
meets_reqs = self.areChangesReadyToBeEnqueued(item.changes, item.event)
dependency_graph = collections.OrderedDict()
self.getDependencyGraph(item.changes[0], dependency_graph, item.event,
quiet=True)
try:
self.getDependencyGraph(item.changes[0], dependency_graph,
item.event, quiet=True)
except exceptions.DependencyLimitExceededError:
self.removeItem(item)
return True, nnfi
# Verify that the cycle dependency graph is correct
cycle = self.cycleForChange(