mirror of
https://github.com/ansible/awx.git
synced 2026-02-24 14:36:00 -03:30
Wrap Django RedisCache to mute exceptions (#14243)
We introduce a thin wrapper over Django's RedisCache so that the functionality of DJANGO_REDIS_IGNORE_EXCEPTIONS is retained while still being able to drop the django-redis dependency. Credit to django-redis's implementation for the idea of using a decorator for this and abstracting out the exception handling logic. Signed-off-by: Rick Elrod <rick@elrod.me>
This commit is contained in:
87
awx/main/cache.py
Normal file
87
awx/main/cache.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import functools
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.cache.backends.base import DEFAULT_TIMEOUT
|
||||||
|
from django.core.cache.backends.redis import RedisCache
|
||||||
|
|
||||||
|
from redis.exceptions import ConnectionError, ResponseError, TimeoutError
|
||||||
|
import socket
|
||||||
|
|
||||||
|
# This list comes from what django-redis ignores and the behavior we are trying
|
||||||
|
# to retain while dropping the dependency on django-redis.
|
||||||
|
IGNORED_EXCEPTIONS = (TimeoutError, ResponseError, ConnectionError, socket.timeout)
|
||||||
|
|
||||||
|
CONNECTION_INTERRUPTED_SENTINEL = object()
|
||||||
|
|
||||||
|
|
||||||
|
def optionally_ignore_exceptions(func=None, return_value=None):
|
||||||
|
if func is None:
|
||||||
|
return functools.partial(optionally_ignore_exceptions, return_value=return_value)
|
||||||
|
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except IGNORED_EXCEPTIONS as e:
|
||||||
|
if settings.DJANGO_REDIS_IGNORE_EXCEPTIONS:
|
||||||
|
return return_value
|
||||||
|
raise e.__cause__ or e
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class AWXRedisCache(RedisCache):
|
||||||
|
"""
|
||||||
|
We just want to wrap the upstream RedisCache class so that we can ignore
|
||||||
|
the exceptions that it raises when the cache is unavailable.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
|
||||||
|
return super().add(key, value, timeout, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions(return_value=CONNECTION_INTERRUPTED_SENTINEL)
|
||||||
|
def _get(self, key, default=None, version=None):
|
||||||
|
return super().get(key, default, version)
|
||||||
|
|
||||||
|
def get(self, key, default=None, version=None):
|
||||||
|
value = self._get(key, default, version)
|
||||||
|
if value is CONNECTION_INTERRUPTED_SENTINEL:
|
||||||
|
return default
|
||||||
|
return value
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
|
||||||
|
return super().set(key, value, timeout, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None):
|
||||||
|
return super().touch(key, timeout, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def delete(self, key, version=None):
|
||||||
|
return super().delete(key, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def get_many(self, keys, version=None):
|
||||||
|
return super().get_many(keys, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def has_key(self, key, version=None):
|
||||||
|
return super().has_key(key, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def incr(self, key, delta=1, version=None):
|
||||||
|
return super().incr(key, delta, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None):
|
||||||
|
return super().set_many(data, timeout, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def delete_many(self, keys, version=None):
|
||||||
|
return super().delete_many(keys, version)
|
||||||
|
|
||||||
|
@optionally_ignore_exceptions
|
||||||
|
def clear(self):
|
||||||
|
return super().clear()
|
||||||
@@ -477,7 +477,7 @@ CELERYBEAT_SCHEDULE = {
|
|||||||
|
|
||||||
# Django Caching Configuration
|
# Django Caching Configuration
|
||||||
DJANGO_REDIS_IGNORE_EXCEPTIONS = True
|
DJANGO_REDIS_IGNORE_EXCEPTIONS = True
|
||||||
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': 'unix:/var/run/redis/redis.sock?db=1'}}
|
CACHES = {'default': {'BACKEND': 'awx.main.cache.AWXRedisCache', 'LOCATION': 'unix:/var/run/redis/redis.sock?db=1'}}
|
||||||
|
|
||||||
# Social Auth configuration.
|
# Social Auth configuration.
|
||||||
SOCIAL_AUTH_STRATEGY = 'social_django.strategy.DjangoStrategy'
|
SOCIAL_AUTH_STRATEGY = 'social_django.strategy.DjangoStrategy'
|
||||||
|
|||||||
Reference in New Issue
Block a user