summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zuul/driver/git/gitconnection.py65
-rw-r--r--zuul/driver/git/gitsource.py3
2 files changed, 47 insertions, 21 deletions
diff --git a/zuul/driver/git/gitconnection.py b/zuul/driver/git/gitconnection.py
index cb5fe84c4..36b7242cd 100644
--- a/zuul/driver/git/gitconnection.py
+++ b/zuul/driver/git/gitconnection.py
@@ -23,6 +23,22 @@ from zuul.connection import BaseConnection
from zuul.driver.git.gitmodel import GitTriggerEvent
from zuul.driver.git.gitwatcher import GitWatcher
from zuul.model import Ref, Branch
+from zuul.zk.change_cache import AbstractChangeCache, ConcurrentUpdateError
+
+
+class GitChangeCache(AbstractChangeCache):
+ log = logging.getLogger("zuul.driver.GitChangeCache")
+
+ CHANGE_TYPE_MAP = {
+ "Ref": Ref,
+ "Branch": Branch,
+ }
+
+ def _getChangeClass(self, change_type):
+ return self.CHANGE_TYPE_MAP[change_type]
+
+ def _getChangeType(self, change):
+ return type(change).__name__
class GitConnection(BaseConnection):
@@ -48,7 +64,6 @@ class GitConnection(BaseConnection):
else:
self.canonical_hostname = 'localhost'
self.projects = {}
- self._change_cache = {}
def toDict(self):
d = super().toDict()
@@ -89,42 +104,45 @@ class GitConnection(BaseConnection):
return refs
def maintainCache(self, relevant):
- remove = {}
- for branch, refschange in self._change_cache.items():
- for ref, change in refschange.items():
- if change not in relevant:
- remove.setdefault(branch, []).append(ref)
- for branch, refs in remove.items():
- for ref in refs:
- del self._change_cache[branch][ref]
- if not self._change_cache[branch]:
- del self._change_cache[branch]
+ for change in self._change_cache:
+ if change not in relevant:
+ self._change_cache.delete(change.cache_stat.key)
+ # TODO: remove entries older than X
+ self._change_cache.cleanup()
def getChange(self, event, refresh=False):
+ key = str((event.project_name, event.ref, event.newrev))
+ change = self._change_cache.get(key)
+ if change:
+ return change
+
if event.ref and event.ref.startswith('refs/heads/'):
branch = event.ref[len('refs/heads/'):]
- change = self._change_cache.get(branch, {}).get(event.newrev)
- if change:
- return change
project = self.getProject(event.project_name)
change = Branch(project)
change.branch = branch
- for attr in ('ref', 'oldrev', 'newrev'):
- setattr(change, attr, getattr(event, attr))
+ change.ref = event.ref
+ change.oldrev = event.oldrev
+ change.newrev = event.newrev
change.url = ""
change.files = self.getChangeFilesUpdated(
event.project_name, change.branch, event.oldrev)
- self._change_cache.setdefault(branch, {})[event.newrev] = change
elif event.ref:
# catch-all ref (ie, not a branch or head)
project = self.getProject(event.project_name)
change = Ref(project)
- for attr in ('ref', 'oldrev', 'newrev'):
- setattr(change, attr, getattr(event, attr))
+ change.ref = event.ref
+ change.oldrev = event.oldrev
+ change.newrev = event.newrev
change.url = ""
else:
- self.log.warning("Unable to get change for %s" % (event,))
- change = None
+ self.log.warning("Unable to get change for %s", event)
+ return None
+
+ try:
+ self._change_cache.set(key, change)
+ except ConcurrentUpdateError:
+ change = self._change_cache.get(key)
return change
def getProjectBranches(self, project, tenant):
@@ -133,6 +151,9 @@ class GitConnection(BaseConnection):
refs if ref.startswith('refs/heads/')]
return branches
+ def getChangeByKey(self, key):
+ return self._change_cache.get(key)
+
def getGitUrl(self, project):
return os.path.join(self.baseurl, project.name)
@@ -156,6 +177,8 @@ class GitConnection(BaseConnection):
self.sched.addTriggerEvent(self.driver_name, event)
def onLoad(self):
+ self.log.debug("Creating Zookeeper change cache")
+ self._change_cache = GitChangeCache(self.sched.zk_client, self)
self.log.debug("Starting Git Watcher")
self._start_watcher_thread()
diff --git a/zuul/driver/git/gitsource.py b/zuul/driver/git/gitsource.py
index 6ee73e38b..ebe5187a3 100644
--- a/zuul/driver/git/gitsource.py
+++ b/zuul/driver/git/gitsource.py
@@ -41,6 +41,9 @@ class GitSource(BaseSource):
def getChangeByURL(self, url, event):
return None
+ def getChangeByKey(self, key):
+ return self.connection.getChangeByKey(key)
+
def getChangesDependingOn(self, change, projects, tenant):
return []