From 3a57fede127d077c0f34e6db63706ba3becc69ae Mon Sep 17 00:00:00 2001 From: Dave Shawley Date: Mon, 20 Feb 2017 07:48:22 -0500 Subject: [PATCH] Cache application name & version on the class. This prevents each status call from doing a pkg_resources resolution which might not be as cheap as it appears to be. --- sprockets_status/handlers.py | 84 +++++++++++++++++++++++------------- tests.py | 10 +++++ 2 files changed, 63 insertions(+), 31 deletions(-) diff --git a/sprockets_status/handlers.py b/sprockets_status/handlers.py index f942e96..47107fd 100644 --- a/sprockets_status/handlers.py +++ b/sprockets_status/handlers.py @@ -1,7 +1,7 @@ import json import pkg_resources -from tornado import concurrent, gen, web +from tornado import web class StatusHandler(web.RequestHandler): @@ -25,12 +25,44 @@ class StatusHandler(web.RequestHandler): """ - def __init__(self, *args, **kwargs): - self.name = 'UNKNOWN' - self.version = '0.0.0' - self.status = 'ok' - self._package_name = None - super(StatusHandler, self).__init__(*args, **kwargs) + OK = 'ok' + FAILURE = 'failed' + + _package_name = None + _application_name = 'UNKNOWN' + _application_version = None + + @property + def application_name(self): + """The application's reported name.""" + self._lookup_package_info() + return self._application_name + + @property + def application_version(self): + """The application's version number.""" + self._lookup_package_info() + return self._application_version + + @property + def application_status(self): + """The application's current status.""" + self._lookup_package_info() + if self.application_name is None: + return self.FAILURE + return self.OK + + @classmethod + def _lookup_package_info(cls): + if cls._package_name is not None: + try: + pkg_info = pkg_resources.get_distribution(cls._package_name) + cls._application_name = pkg_info.project_name + cls._application_version = pkg_info.version + cls._package_name = None + except pkg_resources.ResolutionError: + cls._application_name = None + cls._application_version = None def initialize(self, **kwargs): """ @@ -47,28 +79,12 @@ class StatusHandler(web.RequestHandler): keywords are used. """ + cls = self.__class__ if 'package' in kwargs: - self._package_name = kwargs['package'] + cls._package_name = kwargs['package'] else: - self.name = kwargs.get('name') or self.name - self.version = kwargs.get('version') or self.version - - @gen.coroutine - def prepare(self): - maybe_future = super(StatusHandler, self).prepare() - if concurrent.is_future(maybe_future): - yield maybe_future - - if not self._finished: - if self._package_name is not None: - try: - pkg_info = pkg_resources.get_distribution( - self._package_name) - self.name = pkg_info.project_name - self.version = pkg_info.version - except pkg_resources.ResolutionError: - self.set_status(500) - self.finish() + cls._application_name = kwargs['name'] + cls._application_version = kwargs['version'] def get(self): """ @@ -85,9 +101,15 @@ class StatusHandler(web.RequestHandler): } """ - self.set_status(200) + if self.application_status == self.FAILURE: + self.set_status(500) + else: + self.set_status(200) + self.set_header('Content-Type', 'application/json') - self.write(json.dumps({'name': self.name, - 'version': self.version, - 'status': self.status}).encode('utf-8')) + self.write(json.dumps({ + 'name': self.application_name, + 'version': self.application_version, + 'status': self.application_status + }).encode('utf-8')) self.finish() diff --git a/tests.py b/tests.py index 57f9b8a..baf224e 100644 --- a/tests.py +++ b/tests.py @@ -9,6 +9,11 @@ import sprockets_status.handlers class SimpleStatusTests(testing.AsyncHTTPTestCase): + @classmethod + def setUpClass(cls): + super(SimpleStatusTests, cls).setUpClass() + sprockets_status.handlers.StatusHandler._package_name = None + def get_app(self): return examples.app.make_app() @@ -39,6 +44,11 @@ class SimpleStatusTests(testing.AsyncHTTPTestCase): class PackageLookupTests(testing.AsyncHTTPTestCase): + @classmethod + def setUpClass(cls): + super(PackageLookupTests, cls).setUpClass() + sprockets_status.handlers.StatusHandler._package_name = None + def setUp(self): self.application = None super(PackageLookupTests, self).setUp()