Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Redlock usage documentation #621

Merged
merged 6 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -394,19 +394,25 @@ your `Redlock` will remain available and performant. Now you can protect
access to your resource:

```python
>>> printer_lock.acquire()
True
>>> # Critical section - print stuff here.
>>> printer_lock.release()
>>> if printer_lock.acquire():
... print('printer_lock is locked')
... # Critical section - print stuff here.
... printer_lock.release()
printer_lock is locked
>>> bool(printer_lock.locked())
False
>>>
```

Or you can protect access to your resource inside a context manager:

```python
>>> with printer_lock:
... print('printer_lock is locked')
... # Critical section - print stuff here.
... pass
printer_lock is locked
>>> bool(printer_lock.locked())
False
>>>
```

Expand All @@ -428,12 +434,9 @@ section before it releases its lock).

```python
>>> import time
>>> printer_lock.acquire()
True
>>> bool(printer_lock.locked())
True
>>> # Critical section - print stuff here.
>>> time.sleep(10)
>>> if printer_lock.acquire():
... # Critical section - print stuff here.
... time.sleep(10)
>>> bool(printer_lock.locked())
False
>>>
Expand All @@ -444,12 +447,9 @@ then you can specify your own auto release time (in milliseconds):

```python
>>> printer_lock = Redlock(key='printer', masters={redis}, auto_release_time=15*1000)
>>> printer_lock.acquire()
True
>>> bool(printer_lock.locked())
True
>>> # Critical section - print stuff here.
>>> time.sleep(10)
>>> if printer_lock.acquire():
... # Critical section - print stuff here.
... time.sleep(10)
>>> bool(printer_lock.locked())
True
>>> time.sleep(5)
Expand Down Expand Up @@ -498,8 +498,10 @@ manager fails to acquire the lock, it raises the `QuorumNotAchieved` exception.
... with contextlib.suppress(QuorumNotAchieved):
... with printer_lock_2: # Waits 0.2 seconds; raises QuorumNotAchieved.
... pass
... assert printer_lock_1.locked()
... assert not printer_lock_2.locked()
... print(f"printer_lock_1 is {'locked' if printer_lock_1.locked() else 'unlocked'}")
... print(f"printer_lock_2 is {'locked' if printer_lock_2.locked() else 'unlocked'}")
printer_lock_1 is locked
printer_lock_2 is unlocked
>>>
```

Expand Down
3 changes: 3 additions & 0 deletions pottery/bloom.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
from .base import JSONTypes


# TODO: When we drop support for Python 3.7, stop using @_store_on_self(). Use
# @functools.cached_property() instead.
# https://docs.python.org/3/library/functools.html#functools.cached_property
def _store_on_self(*, attr: str) -> Callable[[F], F]:
"Decorator to store/cache a method's return value as an attribute on self."
def decorator(func: F) -> F:
Expand Down
80 changes: 34 additions & 46 deletions pottery/redlock.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,10 @@ class Redlock(_Scripts):
>>> printer_lock = Redlock(key='printer', masters={redis})
>>> bool(printer_lock.locked())
False
>>> printer_lock.acquire()
True
>>> bool(printer_lock.locked())
True
>>> # Critical section - print stuff here.
>>> if printer_lock.acquire():
... print('printer_lock is locked')
... # Critical section - print stuff here.
printer_lock is locked
>>> printer_lock.release()
>>> bool(printer_lock.locked())
False
Expand All @@ -186,11 +185,9 @@ class Redlock(_Scripts):
(in the event that a process dies inside a critical section before it
releases its lock).

>>> printer_lock.acquire()
True
>>> bool(printer_lock.locked())
True
>>> # Critical section - print stuff here.
>>> if printer_lock.acquire():
... # Critical section - print stuff here.
... time.sleep(10)
>>> time.sleep(10)
>>> bool(printer_lock.locked())
False
Expand All @@ -199,12 +196,9 @@ class Redlock(_Scripts):
then you can specify your own timeout:

>>> printer_lock = Redlock(key='printer', masters={redis}, auto_release_time=15*1000)
>>> printer_lock.acquire()
True
>>> bool(printer_lock.locked())
True
>>> # Critical section - print stuff here.
>>> time.sleep(10)
>>> if printer_lock.acquire():
... # Critical section - print stuff here.
... time.sleep(10)
>>> bool(printer_lock.locked())
True
>>> time.sleep(5)
Expand All @@ -213,21 +207,19 @@ class Redlock(_Scripts):

You can use a Redlock as a context manager:

>>> states = []
>>> with Redlock(key='printer', masters={redis}) as printer_lock:
... states.append(bool(printer_lock.locked()))
... print('printer_lock is locked')
... # Critical section - print stuff here.
>>> states.append(bool(printer_lock.locked()))
>>> states
[True, False]
printer_lock is locked
>>> bool(printer_lock.locked())
False

>>> states = []
>>> with printer_lock:
... states.append(bool(printer_lock.locked()))
... print('printer_lock is locked')
... # Critical section - print stuff here.
>>> states.append(bool(printer_lock.locked()))
>>> states
[True, False]
printer_lock is locked
>>> bool(printer_lock.locked())
False
'''

__slots__ = (
Expand Down Expand Up @@ -617,23 +609,21 @@ def __enter__(self) -> Redlock:

Usage:

>>> states = []
>>> from redis import Redis
>>> redis = Redis(socket_timeout=1)
>>> with Redlock(key='printer', masters={redis}) as printer_lock:
... states.append(bool(printer_lock.locked()))
... print('printer_lock is locked')
... # Critical section - print stuff here.
>>> states.append(bool(printer_lock.locked()))
>>> states
[True, False]
printer_lock is locked
>>> bool(printer_lock.locked())
False

>>> states = []
>>> with printer_lock:
... states.append(bool(printer_lock.locked()))
... print('printer_lock is locked')
... # Critical section - print stuff here.
>>> states.append(bool(printer_lock.locked()))
>>> states
[True, False]
printer_lock is locked
>>> bool(printer_lock.locked())
False
'''
acquired = self.__acquire(
blocking=self.context_manager_blocking,
Expand Down Expand Up @@ -668,23 +658,21 @@ def __exit__(self,

Usage:

>>> states = []
>>> from redis import Redis
>>> redis = Redis(socket_timeout=1)
>>> with Redlock(key='printer', masters={redis}) as printer_lock:
... states.append(bool(printer_lock.locked()))
... print('printer_lock is locked')
... # Critical section - print stuff here.
>>> states.append(bool(printer_lock.locked()))
>>> states
[True, False]
printer_lock is locked
>>> bool(printer_lock.locked())
False

>>> states = []
>>> with printer_lock:
... states.append(bool(printer_lock.locked()))
... print('printer_lock is locked')
... # Critical section - print stuff here.
>>> states.append(bool(printer_lock.locked()))
>>> states
[True, False]
printer_lock is locked
>>> bool(printer_lock.locked())
False
'''
self.__release()
return False
Expand Down