diff options
author | Raghu Udiyar <raghusiddarth@gmail.com> | 2018-01-15 00:12:43 +0530 |
---|---|---|
committer | Jeff Widman <jeff@jeffwidman.com> | 2018-03-23 13:44:15 -0700 |
commit | 6f7a603de9f04ec46d9946c6f5b1cb6e2b913b63 (patch) | |
tree | b21652ca8b029882328ed725972a0c739244568d | |
parent | 111941371daec00a2ecb5d8c29b9b1d35d6aa4ff (diff) | |
download | kazoo-6f7a603de9f04ec46d9946c6f5b1cb6e2b913b63.tar.gz |
feat(recipe): allow non ephemeral locking
Right now if the program taking the lock exits, the lock is also
released implicitly as the zk node is ephemeral. In some usecases
its desirable to make the lock release explicit. For example, in
scripting multiple programs that contend for a lock, or purposeful
failing lock acquirers to detect issues.
The ephemeral flag in acquire() allows for this behavior.
-rw-r--r-- | kazoo/recipe/lock.py | 19 | ||||
-rw-r--r-- | kazoo/tests/test_lock.py | 13 |
2 files changed, 28 insertions, 4 deletions
diff --git a/kazoo/recipe/lock.py b/kazoo/recipe/lock.py index 95a8272..6a50cfb 100644 --- a/kazoo/recipe/lock.py +++ b/kazoo/recipe/lock.py @@ -126,7 +126,7 @@ class Lock(object): self.cancelled = True self.wake_event.set() - def acquire(self, blocking=True, timeout=None): + def acquire(self, blocking=True, timeout=None, ephemeral=True): """ Acquire the lock. By defaults blocks and waits forever. @@ -134,6 +134,8 @@ class Lock(object): :type blocking: bool :param timeout: Don't wait forever to acquire the lock. :type timeout: float or None + :param ephemeral: Don't use ephemeral znode for the lock. + :type ephemeral: bool :returns: Was the lock acquired? :rtype: bool @@ -141,8 +143,16 @@ class Lock(object): :raises: :exc:`~kazoo.exceptions.LockTimeout` if the lock wasn't acquired within `timeout` seconds. + .. warning:: + + When :attr:`ephemeral` is set to False session expiration + will not release the lock and must be handled separately. + .. versionadded:: 1.1 The timeout option. + + .. versionadded:: 2.4.1 + The ephemeral option. """ def _acquire_lock(): @@ -170,7 +180,8 @@ class Lock(object): gotten = False try: gotten = retry(self._inner_acquire, - blocking=blocking, timeout=timeout) + blocking=blocking, timeout=timeout, + ephemeral=ephemeral) except RetryFailedError: pass except KazooException: @@ -192,7 +203,7 @@ class Lock(object): self.wake_event.set() return True - def _inner_acquire(self, blocking, timeout): + def _inner_acquire(self, blocking, timeout, ephemeral=True): # wait until it's our chance to get it.. if self.is_acquired: @@ -212,7 +223,7 @@ class Lock(object): if not node: node = self.client.create(self.create_path, self.data, - ephemeral=True, sequence=True) + ephemeral=ephemeral, sequence=True) # strip off path to node node = node[len(self.path) + 1:] diff --git a/kazoo/tests/test_lock.py b/kazoo/tests/test_lock.py index cae4837..ae907ed 100644 --- a/kazoo/tests/test_lock.py +++ b/kazoo/tests/test_lock.py @@ -6,6 +6,7 @@ from nose.tools import eq_, ok_ from kazoo.exceptions import CancelledError from kazoo.exceptions import LockTimeout +from kazoo.exceptions import NoNodeError from kazoo.testing import KazooTestCase from kazoo.tests import util as test_util @@ -355,6 +356,18 @@ class KazooLockTests(KazooTestCase): lock.acquire() lock.release() + def test_lock_ephemeral(self): + client1 = self._get_client() + client1.start() + lock = client1.Lock(self.lockpath, "ephemeral") + lock.acquire(ephemeral=False) + znode = self.lockpath + '/' + lock.node + client1.stop() + try: + self.client.get(znode) + except NoNodeError: + self.fail("NoNodeError raised unexpectedly!") + def test_lock_timeout(self): timeout = 3 e = self.make_event() |