Mike Bayer avatar Mike Bayer committed 7bafa67

- add redis mutex also
- changelog

Comments (0)

Files changed (5)

+0.2.2
+=====
+- add Redis backend, courtesy Ollie Rutherfurd
+
 0.2.1
 =====
 - move tests into tests/cache namespace

dogpile/cache/__init__.py

-__version__ = '0.2.1'
+__version__ = '0.2.2'
 
 from .region import CacheRegion, register_backend, make_region

dogpile/cache/backends/redis.py

 from __future__ import absolute_import
 from dogpile.cache.api import CacheBackend, NO_VALUE
 from dogpile.cache.util import pickle
-
+import random
+import time
 
 class RedisBackend(CacheBackend):
     """A `Redis <http://redis.io/>`_ backend.
         self.host = arguments.pop('host', 'localhost')
         self.port = arguments.pop('port', 6379)
         self.db = arguments.pop('db', 0)
+        self.distributed_lock = arguments.get('distributed_lock', False)
         self.redis_expiration_time = arguments.pop('redis_expiration_time', 0)
         self.client = self._create_client()
 
         # creates client instace (so test harness can test connection)
         return redis.StrictRedis(host=self.host, port=self.port, db=self.db)
 
+    def get_mutex(self, key):
+        if self.distributed_lock:
+            return RedisLock(lambda: self.client, key)
+        else:
+            return None
+
     def get(self, key):
         value = self.client.get(key)
         if value is None:
 
     def delete(self, key):
         self.client.delete(key)
+
+class RedisLock(object):
+    def __init__(self, client_fn, key):
+        self.client_fn = client_fn
+        self.key = "_lock" + key
+
+    def acquire(self, wait=True):
+        client = self.client_fn()
+        i = 0
+        while True:
+            if client.setnx(self.key, 1):
+                return True
+            elif not wait:
+                return False
+            else:
+                sleep_time = (((i+1)*random.random()) + 2**i) / 2.5
+                time.sleep(sleep_time)
+            if i < 15:
+                i += 1
+
+    def release(self):
+        client = self.client_fn()
+        client.delete(self.key)
+
+

Empty file added.

tests/cache/test_redis_backend.py

-from ._fixtures import _GenericBackendTest
+from ._fixtures import _GenericBackendTest, _GenericMutexTest
 from nose import SkipTest
 
 class _TestRedisConn(object):
             }
     }
 
+
+class RedisDistributedMutexTest(_TestRedisConn, _GenericMutexTest):
+    backend = 'dogpile.cache.redis'
+    config_args = {
+        "arguments":{
+            'host': '127.0.0.1',
+            'port': 6379,
+            'db': 0,
+            'distributed_lock':True,
+            }
+    }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.