From ff291299db4fa6e2890694c475ed9dad090e4942 Mon Sep 17 00:00:00 2001 From: rogelio Date: Sat, 1 Oct 2011 00:48:21 -0500 Subject: [PATCH] Add Redis cache. --- tweepy/cache.py | 81 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/tweepy/cache.py b/tweepy/cache.py index f906d4b..6630c49 100644 --- a/tweepy/cache.py +++ b/tweepy/cache.py @@ -301,4 +301,83 @@ class MemCacheCache(Cache): def flush(self): """Delete all cached entries. NO-OP""" - pass + raise NotImplementedError + +class RedisCache(Cache): + '''Cache running in a redis server''' + + def __init__(self, client, timeout=60, keys_container = 'tweepy:keys', pre_identifier = 'tweepy:'): + Cache.__init__(self, timeout) + self.client = client + self.keys_container = keys_container + self.pre_identifier = pre_identifier + + def _is_expired(self, entry, timeout): + # Returns true if the entry has expired + return timeout > 0 and (time.time() - entry[0]) >= timeout + + def store(self, key, value): + '''Store the key, value pair in our redis server''' + # Prepend tweepy to our key, this makes it easier to identify tweepy keys in our redis server + key = self.pre_identifier + key + # Get a pipe (to execute several redis commands in one step) + pipe = self.client.pipeline() + # Set our values in a redis hash (similar to python dict) + pipe.set(key, pickle.dumps((time.time(), value))) + # Set the expiration + pipe.expire(key, self.timeout) + # Add the key to a set containing all the keys + pipe.sadd(self.keys_container, key) + # Execute the instructions in the redis server + pipe.execute() + + def get(self, key, timeout=None): + '''Given a key, returns an element from the redis table''' + key = self.pre_identifier + key + # Check to see if we have this key + unpickled_entry = self.client.get(key) + if not unpickled_entry: + # No hit, return nothing + return None + + entry = pickle.loads(unpickled_entry) + # Use provided timeout in arguments if provided + # otherwise use the one provided during init. + if timeout is None: + timeout = self.timeout + + # Make sure entry is not expired + if self._is_expired(entry, timeout): + # entry expired, delete and return nothing + self.delete_entry(key) + return None + # entry found and not expired, return it + return entry[1] + + def count(self): + '''Note: This is not very efficient, since it retreives all the keys from the redis + server to know how many keys we have''' + return len(self.client.smembers(self.keys_container)) + + def delete_entry(self, key): + '''Delete an object from the redis table''' + pipe = self.client.pipeline() + pipe.srem(self.keys_container, key) + pipe.delete(key) + pipe.execute() + + def cleanup(self): + '''Cleanup all the expired keys''' + keys = self.client.smembers(self.keys_container) + for key in keys: + entry = self.client.get(key) + if entry: + entry = pickle.loads(entry) + if self._is_expired(entry, self.timeout): + self.delete_entry(key) + + def flush(self): + '''Delete all entries from the cache''' + keys = self.client.smembers(self.keys_container) + for key in keys: + self.delete_entry(key) -- 2.25.1