diff --git a/config/settings/base.py b/config/settings/base.py index aa4adc41b2696a4edef6fcd93c0fd2d8c4edd51e..fc7312a9b7d2933cdf1f74e31a80ee569027bf75 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -218,6 +218,7 @@ ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["retribute.me"]) # CACHES # ------------------------------------------------------------------------------ CACHES = {"default": env.cache()} +CACHE_DEFAULT_EXPIRATION = env.int("CACHE_DEFAULT_EXPIRATION", default=60 * 60 * 12) ASYNC_REDIS_PARAMS = {"address": CACHES["default"]["LOCATION"]} CHANNEL_LAYERS = { "default": { diff --git a/retribute_api/cache.py b/retribute_api/cache.py index a8d2a2d6938a030012d65965696ffed6d1d7d9c3..84d017f50c1978c3ee2ffb00e3b6764d04b3067f 100644 --- a/retribute_api/cache.py +++ b/retribute_api/cache.py @@ -52,15 +52,21 @@ class Redis(Backend): v = await r.get(key) except KeyError: raise self.NotFound(key) + if v is None: + raise self.NotFound(key) try: return json.loads(v) except TypeError: # Null, empty string, etc. return v - async def set(self, key, value): + async def set(self, key, value, expire=None): + if expire is None: + expire = settings.CACHE_DEFAULT_EXPIRATION r = await self.redis() - await r.set(key, json.dumps(value)) + if expire: + return await r.setex(key, expire, json.dumps(value)) + return await r.set(key, json.dumps(value)) async def close(self): if not self._redis: @@ -68,5 +74,12 @@ class Redis(Backend): await self._redis.close() +_DEFAULT = None + + def get_default(): - return Redis(settings.ASYNC_REDIS_PARAMS) + global _DEFAULT + if _DEFAULT: + return _DEFAULT + _DEFAULT = Redis(settings.ASYNC_REDIS_PARAMS) + return _DEFAULT diff --git a/retribute_api/search/consumers.py b/retribute_api/search/consumers.py index ba996f0b21527c3b87181e7c30ddcd200627760d..c7d05c38699677a40d34999774979773d1b69260 100644 --- a/retribute_api/search/consumers.py +++ b/retribute_api/search/consumers.py @@ -36,18 +36,6 @@ def wrapper_500(callback): return callback -def with_cache(f): - async def inner(*args, **kwargs): - c = kwargs.setdefault("cache", cache.get_default()) - try: - return await f(*args, **kwargs) - except Exception: - await c.close() - raise - - return inner - - def ignore_aiohttp_ssl_eror(loop, aiohttpversion="3.5.4"): """Ignore aiohttp #3535 issue with SSL data after close @@ -96,8 +84,7 @@ def ignore_aiohttp_ssl_eror(loop, aiohttpversion="3.5.4"): class SearchSingleConsumer(AsyncHttpConsumer): @wrapper_500 - @with_cache - async def handle(self, body, cache): + async def handle(self, body): lookup_type = self.scope["url_route"]["kwargs"]["lookup_type"] lookup = self.scope["url_route"]["kwargs"]["lookup"] ignore_aiohttp_ssl_eror(asyncio.get_running_loop()) @@ -107,7 +94,7 @@ class SearchSingleConsumer(AsyncHttpConsumer): await json_response(self, 400, {"detail": "Invalid lookup"}) try: async with aiohttp.client.ClientSession(timeout=aiohttp_timeout) as session: - data = await source.get(lookup, session, cache=cache) + data = await source.get(lookup, session, cache=cache.get_default()) profile = sources.result_to_retribute_profile(lookup_type, lookup, data) except (exceptions.SearchError, aiohttp.ClientError) as e: await json_response(self, 400, {"detail": e.message}) @@ -118,9 +105,9 @@ class SearchSingleConsumer(AsyncHttpConsumer): await json_response(self, 200, profile) -async def do_lookup(lookup, lookup_type, session, source, results, cache): +async def do_lookup(lookup, lookup_type, session, source, results): try: - data = await source.get(lookup, session, cache=cache) + data = await source.get(lookup, session, cache=cache.get_default()) profile = sources.result_to_retribute_profile(lookup_type, lookup, data) except ( exceptions.SearchError, @@ -139,8 +126,7 @@ async def do_lookup(lookup, lookup_type, session, source, results, cache): class SearchMultipleConsumer(AsyncHttpConsumer): @wrapper_500 - @with_cache - async def handle(self, body, cache): + async def handle(self, body): if self.scope["method"] == "OPTIONS": return await self.send_response( 200, @@ -181,7 +167,6 @@ class SearchMultipleConsumer(AsyncHttpConsumer): session=session, source=source, results=results, - cache=cache, ) ) try: