Reputation: 48730
I've just set our development Django site to use redis for a cache backend and it was all working fine. I brought down redis to see what would happen, and sure enough Django 404's due to cache backend behaviour. Either the Connection was refused, or various other errors.
Is there any way to instruct Django to ignore Cache errors, and continue processing the normal way? It seems weird that caching is a performance optimization, but can bring down an entire site if it fails.
I tried to write a wrapper around the backend like so:
class CacheClass(redis_backend.CacheClass):
""" Wraps the desired Cache, and falls back to global_settings default on init failure """
def __init__(self, server, params):
try:
super(CacheClass, self).__init__(server, params)
except Exception:
from django.core import cache as _
_.cache = _.get_cache('locmem://')
But that won't work, since I'm trying to set the cache type in the call that sets the cache type. It's all a very big mess.
So, is there any easy way to swallow cache errors? Or to set the default cache backend on failure?
Upvotes: 9
Views: 4293
Reputation: 3
Create a CustomCache
from django.core.cache import caches
from django.core.cache.backends.base import BaseCache
from django.utils.connection import ConnectionProxy
Default_Timeout = 1200 # in seconds
class CustomCache(BaseCache):
def __init__(self):
try:
self.cache = ConnectionProxy(caches, DEFAULT_CACHE_ALIAS)
except Exception as e:
self.cache = None
def get(self, key, default=None):
try:
return self.cache.get(key)
except Exception as exc:
return default
def set(self, key, value, timeout=Default_Timeout):
try:
return self.cache.set(key, value, timeout)
except Exception as exc:
return False
def get_or_set(self, key, callable_func, timeout=Default_Timeout):
try:
return self.cache.get_or_set(key, callable_func, timeout)
except Exception as exc:
return callable_func()
custom_cache = CustomCache()
similarly implement other methods like has_key(), delete(), clear(), all_keys(), etc.
now everywhere import this custom_cache instead of django.core.cache
Upvotes: 0
Reputation: 321
Look at django-cache-fallback:
https://pypi.python.org/pypi/django-cache-fallback/0.2.1
CACHES = {
# Set default cache to FallbackCache
'default': {
'BACKEND': 'cache_fallback.FallbackCache',
},
# Your production main cache (Redis, for example)
'main_cache': {
'BACKEND': 'redis_lock.django_cache.RedisCache',
'LOCATION': redis_url,
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
},
'TIMEOUT': 500,
},
# Use dummy cache to ignore main cache errors and get data from DB
'fallback_cache': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
Upvotes: 5
Reputation: 48730
It doesn't look like there is any good way to do what I want, without writing error handing directly into the methods that the cache backend support. Even if init of the backend fails, some backends will only throw errors on first access to the backend.
What I've done is modified the backend to wrap all methods with error handling that's conditional on a param passed to the constructor. Not as nice as I'd like.. but it's the least intrusive.
Nothing needs to change in the calling code, so the interface, if you will, is maintained.
Upvotes: 1
Reputation: 1704
I haven't used it, but here's a Django snippet that claims to provide a cache backend with a fallback feature: http://djangosnippets.org/snippets/2193/
Upvotes: 0