diff options
author | Zuul <zuul@review.opendev.org> | 2022-06-28 09:30:16 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2022-06-28 09:30:16 +0000 |
commit | 34fe09ca79cccaadcc28c216731a23bacb83d554 (patch) | |
tree | 0bcedda09f7dc22b7b9b2ea2b7fe44cf92116edc /zuul/web/__init__.py | |
parent | ec83f42a75021d4c827c0a14e38dda146960294a (diff) | |
parent | 1bd6a1e92fb6f8f251854a230eed37af5afe72bf (diff) | |
download | zuul-34fe09ca79cccaadcc28c216731a23bacb83d554.tar.gz |
Merge "REST API: cache tenants list"
Diffstat (limited to 'zuul/web/__init__.py')
-rwxr-xr-x | zuul/web/__init__.py | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/zuul/web/__init__.py b/zuul/web/__init__.py index d78bcb918..b24eb4998 100755 --- a/zuul/web/__init__.py +++ b/zuul/web/__init__.py @@ -360,11 +360,20 @@ class ZuulWebAPI(object): self.system = ZuulSystem(self.zk_client) self.zk_nodepool = ZooKeeperNodepool(self.zk_client, enable_node_cache=True) - self.cache = {} - self.cache_time = {} + self.caches = { + 'status': { + 'cache': {}, + 'cache_time': {}, + 'lock': defaultdict(threading.Lock) + }, + 'tenants': { + 'cache': [], + 'cache_time': 0, + 'lock': threading.Lock() + }, + } self.cache_expiry = 1 self.static_cache_expiry = zuulweb.static_cache_expiry - self.status_lock = defaultdict(threading.Lock) @property def log(self): @@ -941,9 +950,7 @@ class ZuulWebAPI(object): return [n for n, t in self.zuulweb.abide.tenants.items() if self._is_authorized(t, claims)] - @cherrypy.expose - @cherrypy.tools.json_out(content_type='application/json; charset=utf-8') - def tenants(self): + def _tenants(self): result = [] for tenant_name, tenant in sorted(self.zuulweb.abide.tenants.items()): queue_size = 0 @@ -960,10 +967,26 @@ class ZuulWebAPI(object): 'projects': len(tenant.untrusted_projects), 'queue': queue_size, }) + return result + + @cherrypy.expose + @cherrypy.tools.json_out(content_type='application/json; charset=utf-8') + def tenants(self): + cache_time = self.caches['tenants']['cache_time'] + if time.time() - cache_time > self.cache_expiry: + with self.caches['tenants']['lock']: + self.caches['tenants']['cache'] = self._tenants() + self.caches['tenants']['cache_time'] = time.time() resp = cherrypy.response + resp.headers["Cache-Control"] = f"public, max-age={self.cache_expiry}" + last_modified = datetime.utcfromtimestamp( + self.caches['tenants']['cache_time'] + ) + last_modified_header = last_modified.strftime('%a, %d %b %Y %X GMT') + resp.headers["Last-modified"] = last_modified_header resp.headers['Access-Control-Allow-Origin'] = '*' - return result + return self.caches['tenants']['cache'] @cherrypy.expose @cherrypy.tools.json_out(content_type='application/json; charset=utf-8') @@ -992,25 +1015,33 @@ class ZuulWebAPI(object): def _getStatus(self, tenant_name): tenant = self._getTenantOrRaise(tenant_name) - if tenant_name not in self.cache or \ - (time.time() - self.cache_time[tenant_name]) > self.cache_expiry: - if self.status_lock[tenant_name].acquire(blocking=False): + cache_times = self.caches['status']['cache_time'] + cache_time = cache_times.get(tenant_name, 0) + if tenant_name not in self.caches['status']['lock'] or \ + (time.time() - cache_time) > self.cache_expiry: + if self.caches['status']['lock'][tenant_name].acquire( + blocking=False + ): try: - self.cache[tenant_name] = self.formatStatus(tenant) - self.cache_time[tenant_name] = time.time() + self.caches['status']['cache'][tenant_name] =\ + self.formatStatus(tenant) + self.caches['status']['cache_time'][tenant_name] =\ + time.time() finally: - self.status_lock[tenant_name].release() - if not self.cache.get(tenant_name): + self.caches['status']['lock'][tenant_name].release() + if not self.caches['status']['cache'].get(tenant_name): # If the cache is empty at this point it means that we didn't # get the lock but another thread is initializing the cache # for the first time. In this case we just wait for the lock # to wait for it to finish. - with self.status_lock[tenant_name]: + with self.caches['status']['lock'][tenant_name]: pass - payload = self.cache[tenant_name] + payload = self.caches['status']['cache'][tenant_name] resp = cherrypy.response resp.headers["Cache-Control"] = f"public, max-age={self.cache_expiry}" - last_modified = datetime.utcfromtimestamp(self.cache_time[tenant_name]) + last_modified = datetime.utcfromtimestamp( + self.caches['status']['cache_time'][tenant_name] + ) last_modified_header = last_modified.strftime('%a, %d %b %Y %X GMT') resp.headers["Last-modified"] = last_modified_header resp.headers['Access-Control-Allow-Origin'] = '*' |