changeset 15:fc5b842de4e9

be a little less aggressive when caching
author Jeff Hammel <jhammel@mozilla.com>
date Wed, 17 Oct 2012 14:59:49 -0700
parents cffb6f681b59
children 31898fb3b7d9
files dogdish/dispatcher.py
diffstat 1 files changed, 62 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/dogdish/dispatcher.py	Wed Oct 17 13:26:22 2012 -0700
+++ b/dogdish/dispatcher.py	Wed Oct 17 14:59:49 2012 -0700
@@ -16,6 +16,7 @@
 
 here = os.path.dirname(os.path.abspath(__file__))
 
+### models
 
 class Application(object):
     """class for storing application.ini data"""
@@ -29,6 +30,53 @@
         self.build_id = config.get('App', 'BuildID')
         self.version = config.get('App', 'Version')
 
+
+class Update(object):
+    """class representing a .mar update file"""
+
+    prefix = 'b2g_update_'
+    suffix = '.mar'
+
+    @classmethod
+    def updates(cls, directory):
+        """returns the updates in a directory"""
+
+        contents = [i for i in os.listdir(directory)
+                    if i.startswith(cls.prefix) and i.endswith(cls.suffix)]
+        contents = set(contents)
+        return contents
+
+    def __init__(self, directory, filename):
+        self.directory = directory
+        self.filename = filename
+        self.path = os.path.join(directory, filename)
+        self.stamp = filename[len(self.prefix):-len(self.suffix)]
+        self.size = os.path.getsize(self.path)
+
+        # cached properties
+        self._application = None
+        self._hash = None
+
+    def application(self):
+        """
+        returns the path to the application.ini
+        associated with this update
+        """
+
+        if not self._application:
+            application_ini = 'application_%s.ini' % self.stamp
+            application_ini = os.path.join(self.directory, application_ini)
+            assert os.path.exists(application_ini)
+            self._application = Application(application_ini)
+        return self._application
+
+    def hash(self):
+        if not self._hash:
+            # compute the hash
+            with file(self.path) as f:
+                self._hash = hashlib.sha512(f.read()).hexdigest()
+        return self._hash
+
 ### request handlers
 
 class Handler(object):
@@ -72,13 +120,13 @@
 
     def __call__(self):
 
-        update_path = os.path.join(self.app.directory, self.app.current_update)
         body = self.body
         query = {}
         dogfood_id = self.request.GET.get('dogfood_id')
         if dogfood_id:
             query['dogfooding_prerelease_id'] = dogfood_id
-        application = self.app.updates[self.app.current_update]
+        current_update = self.app.current_update
+        application = current_update.application()
         query['build_id'] = application.build_id
         query['version'] = application.version
 
@@ -88,14 +136,11 @@
         else:
             query = ''
 
-        # compute the hash
-        with file(update_path) as f:
-            sha512 = hashlib.sha512(f.read()).hexdigest()
 
         # template variables
-        variables = dict(update=self.app.current_update,
-                         size=os.path.getsize(update_path),
-                         hash=sha512,
+        variables = dict(update=current_update.filename,
+                         size=current_update.size,
+                         hash=current_update.hash(),
                          query=query)
 
         return Response(content_type='text/xml',
@@ -118,8 +163,6 @@
         # cache
         self.updates = {}
         self.current_update = None
-        self.current_stamp = '0000-00-00_000000'
-        self.cached_response = None
 
         # scan directory
         self.scan()
@@ -130,13 +173,10 @@
 
         request = Request(environ)
         new = self.scan()
-        if (not new) and (self.cached_response is not None):
-            return self.cached_response(environ, start_response)
         for h in self.handlers:
             if h.match(request):
                 handler = h(self, request)
                 res = handler()
-                self.cached_response = res
                 break
         else:
             res = exc.HTTPNotFound()
@@ -148,25 +188,21 @@
         scan the directory for updates
         returns True if new updates are found, False otherwise
         """
-        prefix = 'b2g_update_'
-        suffix = '.mar'
-        contents = [i for i in os.listdir(self.directory)
-                    if i.startswith(prefix) and i.endswith(suffix)]
-        contents = set(contents)
+
+        # check for new updates
+        contents = Update.updates(self.directory)
         new = contents.difference(self.updates.keys())
         if not new:
             # directory contents unchanged from cached values
             return False
 
         for update in new:
-            stamp = update[len(prefix):-len(suffix)]
-            application_ini = 'application_%s.ini' % stamp
-            application_ini = os.path.join(self.directory, application_ini)
-            assert os.path.exists(application_ini)
-            self.updates[update] = Application(application_ini)
-            if stamp > self.current_stamp:
-                self.current_update = update
-                self.current_stamp = stamp
+            self.updates[update] = Update(self.directory, update)
+            if self.current_update:
+                if self.updates[update].stamp > self.current_update.stamp:
+                    self.current_update = self.updates[update]
+            else:
+                self.current_update = self.updates[update]
 
         # TODO: could remove old files from the cache if not found in contents