[z3-checkins] r31937 - z3/jsonserver/branch/merge/concatresource

reebalazs at codespeak.net reebalazs at codespeak.net
Fri Sep 1 17:10:39 CEST 2006


Author: reebalazs
Date: Fri Sep  1 17:10:36 2006
New Revision: 31937

Modified:
   z3/jsonserver/branch/merge/concatresource/README
   z3/jsonserver/branch/merge/concatresource/cachingadapter.py
   z3/jsonserver/branch/merge/concatresource/concatfileresource.py
   z3/jsonserver/branch/merge/concatresource/directives.py
   z3/jsonserver/branch/merge/concatresource/meta.py
   z3/jsonserver/branch/merge/concatresource/resource.py
Log:
Enhance caching for debugging options

- implement lmt_check_period and caching=memory options for easier degugging

- fix a rounding bug that cause If-Modified-Since requests replied
  wrongly in some cases, causing the resource to be cooked over

Modified: z3/jsonserver/branch/merge/concatresource/README
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/README	(original)
+++ z3/jsonserver/branch/merge/concatresource/README	Fri Sep  1 17:10:36 2006
@@ -37,7 +37,7 @@
 observation: in Z3 the original resources attempt to handle the cache
 headers correctly but never really check if the file gets changed on the
 filesystem (only on restart). If this is really a problem and not just I
-believe, then it is fixed in my code.
+believe, then it is fixed in my code. (Read more in the Caching part.)
 
 More information on this issue:
 
@@ -52,7 +52,7 @@
            name="test.js"
            files="test1.js
                   test2.js"
-		   compress_level="full"
+           compress_level="full"
     />
 
 Some explanation:
@@ -69,14 +69,69 @@
 - Specifying "none" will leave your resource uncompressed. This
   can be useful for debugging.
 
+Caching control
+---------------
+
+You have some possibility to control how caching of resources are done.
+
+    <browser:concatresource
+           name="test.js"
+           files="test1.js
+                  test2.js"
+           caching="memory"
+           lmt_check_period="10.0"
+    />
+
+The attribute "lmt_checking_period" controls how often the file
+modification dates are checked from the filesystem. By default this is
+60.0, this means that once the file modification is checked, it will not be
+checked before the next 60 seconds elapses. In other words, if you change
+the files on the filesystem, it will cause a maximum of this long delay
+until the changes propagate to the rendered resources. For debugging this
+can be set to 0 to allow immediate changes, however in production this
+setup would cause the files often looked up in the filesystem, which,
+especially with badly implemented filesystems can cause a problem. This
+feature is already an enhancement to the original Zope 3 resource
+implementation where, unless running in debug mode, changes in the resource
+files will require a restart to become visible in the result.
+
+The attribute "caching", when set to "memory", will result that the cooked
+resource will be cached in memory and looked up from them as long as the
+files are unchanged. This, especially with compress options, can cause a
+speedup in rendering the resources. However, in normal operation this is
+not necessary at all, since if caching is set up properly, the browser and
+the upstream cache asks via the "If-Modified-Since" headers if the resource
+has been changed recently, and the resource itself is queried only when
+needed, independently of the setup of this option. While debugging,
+however, when browser caching is forced to switch off, without this option
+the resource would be cooked each time the browser reloads the dependent
+page, so in this case setting "caching" to "memory" causes a significant
+speedup in these cases. In production however, is not only unnecessary but
+also causes an additional memory consumption.
+
+Debug setup
+-----------
+
+To summarize with an example, the following settings are advisable while
+debugging:
+
+   <browser:concatresource
+           name="test.js"
+           files="test1.js
+                  test2.js"
+           compress_level="none"
+           caching="memory"
+           lmt_check_period="10.0"
+    />
+
 Release notes
 -------------
 
-In Zope 2.9.2 there is Five 1.3.3 included. This contains a but that
+In Zope 2.9.2 there is Five 1.3.3 included. This contains a bug that
 the resources will never be looked up from the
 application root.
 
 To fix this, you need to update Five to version 1.3.5, or update Zope
-to version 2.9.3 (not available of the time of writing this).
+to version >= 2.9.3.
 
 

Modified: z3/jsonserver/branch/merge/concatresource/cachingadapter.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/cachingadapter.py	(original)
+++ z3/jsonserver/branch/merge/concatresource/cachingadapter.py	Fri Sep  1 17:10:36 2006
@@ -8,23 +8,19 @@
     'Adapts a ContextFile to a cached resource'
     implements(ICachedResource)
 
-    # this is a period in secs within what the resource
-    # modification time is never checked.
-    # (if 0, always checked)
-    # XXX actually this should be kept 0 for debugging and like a minute
-    # XXX for production
-    lmt_check_period = 60.0
-    ##lmt_check_period = 0
-
     def __init__(self, context):
         self.context = context
         self.lmt_last_checked = 0
+        self.data_last_fetched = 0
     
     def _fetchdata(self):
         try:
             result = self._contents
+            ##print "*****Resource from cached"
         except AttributeError:
             result = self._contents = self.context.getContents()
+            self.data_last_fetched = time()
+            ##print "*****Resource kooked"
         return result
 
     def _deldata(self):
@@ -59,3 +55,6 @@
             
     lmt = property(lambda self: self._fetchlm()['lmt'])
     lmh = property(lambda self: self._fetchlm()['lmh'])
+
+    caching = property(lambda self: self.context.caching)
+    lmt_check_period = property(lambda self: self.context.lmt_check_period)

Modified: z3/jsonserver/branch/merge/concatresource/concatfileresource.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/concatfileresource.py	(original)
+++ z3/jsonserver/branch/merge/concatresource/concatfileresource.py	Fri Sep  1 17:10:36 2006
@@ -24,7 +24,7 @@
     '''
     implements(IContextFile)
 
-    def __init__(self, pathlist, name, compress_level):
+    def __init__(self, pathlist, name, compress_level, caching, lmt_check_period):
         # Path is now a list.
         assert isinstance(pathlist, (list, tuple))
         # check all files, just to raise error if don't exist
@@ -34,6 +34,8 @@
         self.pathlist_base = pathlist
         self.__name__ = name
         self.compress_level = compress_level
+        self.caching = caching
+        self.lmt_check_period = lmt_check_period
         # markers for pathlist modification
         self.pathlist = []
         self.fileslist_changed = None

Modified: z3/jsonserver/branch/merge/concatresource/directives.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/directives.py	(original)
+++ z3/jsonserver/branch/merge/concatresource/directives.py	Fri Sep  1 17:10:36 2006
@@ -1,7 +1,7 @@
 from zope.interface import Interface
 from zope.configuration.fields import GlobalObject, Tokens, Path, \
      PythonIdentifier, MessageID
-from zope.schema import TextLine, Text, Id, Choice
+from zope.schema import TextLine, Text, Id, Choice, Float
 from zope.app.security.fields import Permission
 from fields import PathList
 from zope.app.component.metadirectives import IBasicViewInformation
@@ -36,3 +36,21 @@
         values=(u'none', u'safe', u'full'),
         required=False,
         )
+
+    caching = Choice(
+        title=u"Caching strategy",
+        description=u"Enables caching in memory for faster debugging, by default not enabled.",
+        values=(u'default', u'memory'),
+        required=False,
+        )
+
+    lmt_check_period = Float(
+        title=u"Last modification time checking",
+        description=u"""Sets a grace period in seconds, until which the last modification times
+                        are never fetched again from the filesystem. In other words, the system will
+                        react after this time for recent changes. For debugging, it is best
+                        to set this to 0, for production it can be left to the default 60.0""",
+        required=False,
+        )
+
+

Modified: z3/jsonserver/branch/merge/concatresource/meta.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/meta.py	(original)
+++ z3/jsonserver/branch/merge/concatresource/meta.py	Fri Sep  1 17:10:36 2006
@@ -39,7 +39,9 @@
         },
     }
 
-def concatresource(_context, name, files=None, compress_level='safe', layer=_layer, permission='zope.Public'):
+def concatresource(_context, name, files=None, compress_level='safe',
+        caching='default', lmt_check_period=60.0,
+        layer=_layer, permission='zope.Public'):
 
     if not files:
         raise ConfigurationError(
@@ -78,7 +80,8 @@
 
         checker = NamesChecker(allowed_names, permission)
 
-    factory = res_factory(res, name, compress_level, resource_factory=new_class, checker=checker)
+    factory = res_factory(res, name, compress_level, caching, lmt_check_period,
+            resource_factory=new_class, checker=checker)
 
     if __pre_3_2__:
         _context.action(

Modified: z3/jsonserver/branch/merge/concatresource/resource.py
==============================================================================
--- z3/jsonserver/branch/merge/concatresource/resource.py	(original)
+++ z3/jsonserver/branch/merge/concatresource/resource.py	Fri Sep  1 17:10:36 2006
@@ -57,6 +57,14 @@
         request = self.request
         response = request.response
 
+        # Control in-memory caching
+        cache_in_memory = self.context.caching == 'memory'
+        if cache_in_memory:
+            last_mod = file.lmt
+            if last_mod > file.data_last_fetched:
+                # force delete file contents
+                file.purgeData()
+
         # HTTP If-Modified-Since header handling. This is duplicated
         # from OFS.Image.Image - it really should be consolidated
         # somewhere...
@@ -75,8 +83,9 @@
             try:    mod_since=long(timeFromDateTimeString(header))
             except: mod_since=None
             if mod_since is not None:
-                last_mod = file.lmt
-                if last_mod > 0 and last_mod <= mod_since:
+                if not cache_in_memory:
+                    last_mod = file.lmt
+                if last_mod > 0 and int(last_mod) <= mod_since:
                     response.setStatus(304)
                     return ''
 
@@ -85,8 +94,10 @@
         # Cache for one day
         response.setHeader('Cache-Control', 'public,max-age=86400')
         data = file.data
-        # force delete file contents
-        file.purgeData()
+
+        if not cache_in_memory:
+            # force delete file contents
+            file.purgeData()
 
         return data
 
@@ -104,10 +115,13 @@
     factory = None
     resource = None
 
-    def __init__(self, path, name, compress_level, resource_factory=None, checker=None):
+    def __init__(self, path, name, compress_level, caching, lmt_check_period,
+                resource_factory=None, checker=None):
         self.__name = name
         self.__path = path
         self.__compress_level = compress_level
+        self.__caching = caching
+        self.__lmt_check_period = lmt_check_period
         if resource_factory is not None:
             self.resource = resource_factory
         # z3 only
@@ -118,7 +132,8 @@
             rsrc = self.__rsrc
         except AttributeError:
             # Delayed creation. That assures that registry is set up by this time.
-            rsrc = self.__rsrc = ICachedResource(self.factory(self.__path, self.__name, self.__compress_level))
+            rsrc = self.__rsrc = ICachedResource(self.factory(self.__path, self.__name,
+                    self.__compress_level, self.__caching, self.__lmt_check_period))
         resource = self.resource(rsrc, request)
         # z3 only
         resource.__name__ = self.__name


More information about the z3-checkins mailing list