Created
October 13, 2015 06:33
-
-
Save ostcar/b42dbe11a13ac0e7f88e to your computer and use it in GitHub Desktop.
redis get_or_set
This file contains 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
class RedisCache(_RedisCache): | |
""" | |
Wrapper to redis cache that creates status keys for the time a value is | |
created. | |
Idea from https://github.com/funkybob/puppy | |
""" | |
def get_or_set(self, key, callback, timeout=None, update_time=6): | |
""" | |
Get a key if it exists. Creates it if other case. | |
Sets a status key for the time the value is created, so other workers | |
do not created the same content in the meantime. | |
""" | |
# If redis is disabled, then we can call the callback immediately | |
if not settings.USE_REDIS_CACHE: | |
return callback() | |
redis = self.client.get_client() | |
# Key and status key | |
key = self.make_key(key) | |
state_key = key + ':status' | |
# Get the value | |
value = redis.get(key) | |
while value is None: | |
# Try to gain an updating lock | |
if redis.set(state_key, 'updating', ex=update_time, nx=True): | |
try: | |
# TODO: log how long callback needs. If it needs more then | |
# update_time, it should write a warning. | |
value = self.client.encode(callback()) | |
# Resolve our timeout value | |
if timeout is None: | |
timeout = self.default_timeout | |
# Set the value | |
redis.set(key, value, ex=timeout) | |
finally: | |
# If the key is deleted it can not be recreated before the | |
# state_key expires. So the state_key has to be deleted. | |
redis.delete(state_key) | |
# Someone else is already updating the key, but we don't have a value | |
# to return, so we have to wait | |
else: | |
sleep(0.1) | |
value = redis.get(key) | |
try: | |
return self.client.decode(value) | |
except: | |
# If value can not be decoded, then delete it from the cache | |
redis.delete(key) | |
raise |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment