summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJames E. Blair <jim@acmegating.com>2022-12-19 14:01:05 -0800
committerJames E. Blair <jim@acmegating.com>2023-01-05 14:08:10 -0800
commita0ed933fa432fd93b34deeac77c9d45fda34f432 (patch)
tree3ea187dbf63b54599a6a2b305de96474a4678e56 /tests
parentcb40ddc7db83ddda48c5aede7e61e10b42d6845b (diff)
downloadzuul-a0ed933fa432fd93b34deeac77c9d45fda34f432.tar.gz
Track object versions in the Buildset object
This further reduces the number of ZK object reads during pipeline refreshes by tracking when builds and frozen jobs are updated. During the phases of a build where we know no updates can occur, we already avoid refreshing the Build and FrozenJob objects. But, for example, while a build is running we have to continually refresh it to see if it has completed. We can avoid this by recording expected version information in ZK and only refresh those objects if we know our local copy is out of date. We can store the latest ZK object version of FrozenJob and Build objects on the Buildset. On pipeline refresh, we currently always refresh the buildset object, which means that when we prepare to refresh the FrozenJob or Build objects underneath a Buildset, we will have information about the latest versions of those objects in ZK and can compare to the versions we currently have in memory to decide if we need to refresh them. This should reduce the number of reads in a pipeline refresh by about 50%. But it will cause more writes, in that we will update the Buildset object each time we modify one of its children. This may affect pipeline processing times but the impact should be very small. We will use version numbers (rather than transaction ids) because they are predictable, and updating the buildset first with the predicted next version before updating the child avoids issues caused by a crash between those two steps. Since it is typical for many objects to be created at once, we do optimize the case where the objects are initially created and we avoid making an update to the BuildSet in that case so that we don't repeatedly write the buildset object. Change-Id: I3824af6149bf27c41a8d895fc682236bd0d91f6b
Diffstat (limited to 'tests')
-rw-r--r--tests/unit/test_model.py4
-rw-r--r--tests/unit/test_model_upgrade.py39
2 files changed, 43 insertions, 0 deletions
diff --git a/tests/unit/test_model.py b/tests/unit/test_model.py
index aed40b94e..98f971948 100644
--- a/tests/unit/test_model.py
+++ b/tests/unit/test_model.py
@@ -32,7 +32,9 @@ import zuul.lib.connections
from tests.base import BaseTestCase, FIXTURE_DIR
from zuul.lib.ansible import AnsibleManager
from zuul.lib import tracing
+from zuul.model_api import MODEL_API
from zuul.zk.zkobject import LocalZKContext
+from zuul.zk.components import COMPONENT_REGISTRY
from zuul import change_matcher
@@ -44,6 +46,8 @@ class Dummy(object):
class TestJob(BaseTestCase):
def setUp(self):
+ COMPONENT_REGISTRY.registry = Dummy()
+ COMPONENT_REGISTRY.registry.model_api = MODEL_API
self._env_fixture = self.useFixture(
fixtures.EnvironmentVariable('HISTTIMEFORMAT', '%Y-%m-%dT%T%z '))
super(TestJob, self).setUp()
diff --git a/tests/unit/test_model_upgrade.py b/tests/unit/test_model_upgrade.py
index f392e8c3e..a5a49bed4 100644
--- a/tests/unit/test_model_upgrade.py
+++ b/tests/unit/test_model_upgrade.py
@@ -254,6 +254,45 @@ class TestModelUpgrade(ZuulTestCase):
result='SUCCESS', changes='1,1'),
], ordered=False)
+ @model_version(11)
+ def test_model_11_12(self):
+ # This excercises the upgrade to store build/job versions
+ first = self.scheds.first
+ second = self.createScheduler()
+ second.start()
+ self.assertEqual(len(self.scheds), 2)
+ for _ in iterate_timeout(10, "until priming is complete"):
+ state_one = first.sched.local_layout_state.get("tenant-one")
+ if state_one:
+ break
+
+ for _ in iterate_timeout(
+ 10, "all schedulers to have the same layout state"):
+ if (second.sched.local_layout_state.get(
+ "tenant-one") == state_one):
+ break
+
+ self.executor_server.hold_jobs_in_build = True
+ with second.sched.layout_update_lock, second.sched.run_handler_lock:
+ A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
+ self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
+ self.waitUntilSettled(matcher=[first])
+
+ self.model_test_component_info.model_api = 12
+ with first.sched.layout_update_lock, first.sched.run_handler_lock:
+ self.executor_server.hold_jobs_in_build = False
+ self.executor_server.release()
+ self.waitUntilSettled(matcher=[second])
+
+ self.waitUntilSettled()
+ self.assertHistory([
+ dict(name='project-merge', result='SUCCESS', changes='1,1'),
+ dict(name='project-test1', result='SUCCESS', changes='1,1'),
+ dict(name='project-test2', result='SUCCESS', changes='1,1'),
+ dict(name='project1-project2-integration',
+ result='SUCCESS', changes='1,1'),
+ ], ordered=False)
+
class TestGithubModelUpgrade(ZuulTestCase):
config_file = 'zuul-github-driver.conf'