Created
December 4, 2014 12:29
-
-
Save hagai26/0f1c27e24788242dc3b9 to your computer and use it in GitHub Desktop.
flask-cache decorator with caching lock (no two clients inside same view)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
flask.ext.cache before (assume using redis) | |
~~~~~~~~~~~~~~ | |
Adds support for caching before work | |
""" | |
import functools | |
import logging | |
from flask import request, current_app | |
from db import redis | |
logger = logging.getLogger(__name__) | |
def cached_before(cache, timeout=None, key_prefix='view/%s', unless=None): | |
def decorator(f): | |
@functools.wraps(f) | |
def decorated_function(*args, **kwargs): | |
#: Bypass the cache entirely. | |
if callable(unless) and unless() is True: | |
return f(*args, **kwargs) | |
try: | |
cache_key = decorated_function.make_cache_key(*args, **kwargs) | |
rv = cache.get(cache_key) | |
except Exception: | |
if current_app.debug: | |
raise | |
logger.exception("Exception possibly due to cache backend.") | |
return f(*args, **kwargs) | |
if rv is None: | |
lock = redis.lock(cache_key) | |
lock.acquire(blocking=True) | |
try: | |
rv = cache.get(cache_key) | |
if rv is None: | |
rv = f(*args, **kwargs) | |
try: | |
cache.set(cache_key, rv, timeout=decorated_function.cache_timeout) | |
except Exception: | |
if current_app.debug: | |
raise | |
logger.exception("Exception possibly due to cache backend.") | |
return rv | |
finally: | |
lock.release() | |
return rv | |
def make_cache_key(*args, **kwargs): | |
if callable(key_prefix): | |
cache_key = key_prefix() | |
elif '%s' in key_prefix: | |
cache_key = key_prefix % request.path | |
else: | |
cache_key = key_prefix | |
return cache_key | |
decorated_function.uncached = f | |
decorated_function.cache_timeout = timeout | |
decorated_function.make_cache_key = make_cache_key | |
return decorated_function | |
return decorator |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment