diff options
author | Dan McGee <dan@archlinux.org> | 2010-05-04 10:53:40 -0500 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2010-05-04 10:53:40 -0500 |
commit | 4b7335f7137c587e775013d49bccc28bc32387c8 (patch) | |
tree | 6af5a46efe4eb3618afcc5cac72906e46d614a3d | |
parent | c546630ad8609bf30b6ac24326bc7f04aac8d99c (diff) |
Add a hacked version of Django UpdateCacheMiddlewarerelease_2010-05-04
This is to address a rather large issue with caching of feed objects in
Django. Because they are built up using an XML library that does multiple
writes on a file-like object, a single feed object, even when pulled from
memcached, generates 1582 writes to the open socket rather than the optimal
one it could do.
Some version of this fix will be making it upstream, but I need to figure
out how to approach that before I do so and for now this will address one of
our larger performance issues on the live site since the packages feed is
hit as often as it is.
Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r-- | main/middleware.py | 52 | ||||
-rw-r--r-- | settings.py | 2 |
2 files changed, 53 insertions, 1 deletions
diff --git a/main/middleware.py b/main/middleware.py index db2c1104..4d343b41 100644 --- a/main/middleware.py +++ b/main/middleware.py @@ -14,3 +14,55 @@ def get_user(): '''Get the currently logged in request.user''' return user_holder.user +# begin copy of stock Django UpdateCacheMiddleware +# this is to address feeds caching issue which makes it horribly +# unperformant + +from django.conf import settings +from django.core.cache import cache +from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age + +class UpdateCacheMiddleware(object): + """ + Response-phase cache middleware that updates the cache if the response is + cacheable. + + Must be used as part of the two-part update/fetch cache middleware. + UpdateCacheMiddleware must be the first piece of middleware in + MIDDLEWARE_CLASSES so that it'll get called last during the response phase. + """ + def __init__(self): + self.cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS + self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX + self.cache_anonymous_only = getattr(settings, 'CACHE_MIDDLEWARE_ANONYMOUS_ONLY', False) + + def process_response(self, request, response): + """Sets the cache, if needed.""" + if not hasattr(request, '_cache_update_cache') or not request._cache_update_cache: + # We don't need to update the cache, just return. + return response + if request.method != 'GET': + # This is a stronger requirement than above. It is needed + # because of interactions between this middleware and the + # HTTPMiddleware, which throws the body of a HEAD-request + # away before this middleware gets a chance to cache it. + return response + if not response.status_code == 200: + return response + # Try to get the timeout from the "max-age" section of the "Cache- + # Control" header before reverting to using the default cache_timeout + # length. + timeout = get_max_age(response) + if timeout == None: + timeout = self.cache_timeout + elif timeout == 0: + # max-age was set to 0, don't bother caching. + return response + patch_response_headers(response, timeout) + if timeout: + response.content = response.content + cache_key = learn_cache_key(request, response, timeout, self.key_prefix) + cache.set(cache_key, response, timeout) + return response + +# vim: set ts=4 sw=4 et: diff --git a/settings.py b/settings.py index 61ed067c..88adf19d 100644 --- a/settings.py +++ b/settings.py @@ -43,7 +43,7 @@ TEMPLATE_LOADERS = ( ) MIDDLEWARE_CLASSES = ( - 'django.middleware.cache.UpdateCacheMiddleware', + 'main.middleware.UpdateCacheMiddleware', "django.contrib.sessions.middleware.SessionMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", 'django.middleware.http.ConditionalGetMiddleware', |