brotli: degrade gracefully when redis is missing

This commit is contained in:
codl 2021-03-12 12:12:18 +01:00
parent 785d0509af
commit f10b9dac80
1 changed files with 30 additions and 26 deletions

View File

@ -5,6 +5,7 @@ from hashlib import sha256
import redis as libredis import redis as libredis
import os.path import os.path
import mimetypes import mimetypes
from redis.exceptions import RedisError
class BrotliCache(object): class BrotliCache(object):
@ -34,32 +35,35 @@ class BrotliCache(object):
digest = sha256(body).hexdigest() digest = sha256(body).hexdigest()
cache_key = 'brotlicache:{}'.format(digest) cache_key = 'brotlicache:{}'.format(digest)
encbody = self.redis.get(cache_key) try:
response.headers.set('brotli-cache', 'HIT') encbody = self.redis.get(cache_key)
if not encbody: response.headers.set('brotli-cache', 'HIT')
response.headers.set('brotli-cache', 'MISS') if not encbody:
lock_key = 'brotlicache:lock:{}'.format(digest) response.headers.set('brotli-cache', 'MISS')
if self.redis.set(lock_key, 1, nx=True, ex=10): lock_key = 'brotlicache:lock:{}'.format(digest)
mode = ( if self.redis.set(lock_key, 1, nx=True, ex=10):
brotli_.MODE_TEXT mode = (
if response.content_type.startswith('text/') brotli_.MODE_TEXT
else brotli_.MODE_GENERIC) if response.content_type.startswith('text/')
t = Thread( else brotli_.MODE_GENERIC)
target=self.compress_and_cache, t = Thread(
args=(cache_key, lock_key, body, mode)) target=self.compress_and_cache,
t.start() args=(cache_key, lock_key, body, mode))
if self.timeout > 0: t.start()
t.join(self.timeout) if self.timeout > 0:
encbody = self.redis.get(cache_key) t.join(self.timeout)
if not encbody: encbody = self.redis.get(cache_key)
response.headers.set('brotli-cache', 'TIMEOUT') if not encbody:
else: response.headers.set('brotli-cache', 'TIMEOUT')
response.headers.set('brotli-cache', 'LOCKED') else:
if encbody: response.headers.set('brotli-cache', 'LOCKED')
response.headers.set('content-encoding', 'br') if encbody:
response.headers.set('vary', 'accept-encoding') response.headers.set('content-encoding', 'br')
response.set_data(encbody) response.headers.set('vary', 'accept-encoding')
return response response.set_data(encbody)
return response
except RedisError:
response.headers.set('brotli-cache', 'ERROR')
return response return response