diff --git a/doc/source/zuul.rst b/doc/source/zuul.rst index 21d3bae1c5..4c5a6243a8 100644 --- a/doc/source/zuul.rst +++ b/doc/source/zuul.rst @@ -114,6 +114,11 @@ zuul starting jobs for a change. Used by zuul-server only. ``status_url=https://zuul.example.com/status`` +**status_expiry** + Zuul will cache the status.json file for this many seconds. This is an + optional value and ``1`` is used by default. + ``status_expiry=1`` + **url_pattern** If you are storing build logs external to the system that originally ran jobs and wish to link to those logs when Zuul makes comments on diff --git a/zuul/cmd/server.py b/zuul/cmd/server.py index 06ea780099..d7de85a45d 100755 --- a/zuul/cmd/server.py +++ b/zuul/cmd/server.py @@ -163,7 +163,11 @@ class Server(zuul.cmd.ZuulApp): merger = zuul.merger.client.MergeClient(self.config, self.sched) gerrit = zuul.trigger.gerrit.Gerrit(self.config, self.sched) timer = zuul.trigger.timer.Timer(self.config, self.sched) - webapp = zuul.webapp.WebApp(self.sched) + if self.config.has_option('zuul', 'status_expiry'): + cache_expiry = self.config.getint('zuul', 'status_expiry') + else: + cache_expiry = 1 + webapp = zuul.webapp.WebApp(self.sched, cache_expiry=cache_expiry) rpc = zuul.rpclistener.RPCListener(self.config, self.sched) gerrit_reporter = zuul.reporter.gerrit.Reporter(gerrit) smtp_reporter = zuul.reporter.smtp.Reporter( diff --git a/zuul/webapp.py b/zuul/webapp.py index af558a0cba..fc52e070f3 100644 --- a/zuul/webapp.py +++ b/zuul/webapp.py @@ -15,6 +15,7 @@ import logging import threading +import time from paste import httpserver import webob from webob import dec @@ -23,10 +24,13 @@ from webob import dec class WebApp(threading.Thread): log = logging.getLogger("zuul.WebApp") - def __init__(self, scheduler, port=8001): + def __init__(self, scheduler, port=8001, cache_expiry=1): threading.Thread.__init__(self) self.scheduler = scheduler self.port = port + self.cache_expiry = cache_expiry + self.cache_time = 0 + self.cache = None self.daemon = True self.server = httpserver.serve(dec.wsgify(self.app), host='0.0.0.0', port=self.port, start_loop=False) @@ -40,11 +44,17 @@ class WebApp(threading.Thread): def app(self, request): if request.path != '/status.json': raise webob.exc.HTTPNotFound() - try: - ret = self.scheduler.formatStatusJSON() - except: - self.log.exception("Exception formatting status:") - raise - response = webob.Response(body=ret, content_type='application/json') + if (not self.cache or + (time.time() - self.cache_time) > self.cache_expiry): + try: + self.cache = self.scheduler.formatStatusJSON() + # Call time.time() again because formatting above may take + # longer than the cache timeout. + self.cache_time = time.time() + except: + self.log.exception("Exception formatting status:") + raise + response = webob.Response(body=self.cache, + content_type='application/json') response.headers['Access-Control-Allow-Origin'] = '*' return response