Skip to content

Commit

Permalink
Improve RedisSimpleQueue docstrings (#559)
Browse files Browse the repository at this point in the history
  • Loading branch information
brainix authored Dec 29, 2021
1 parent 9997c20 commit 687d41a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ venv ?= venv
init upgrade: formulae := {openssl,readline,xz,redis}
python upgrade: version ?= 3.10.1
upgrade: requirements ?= requirements-to-freeze.txt
delete-keys: pattern ?= tmp:*


.PHONY: install
Expand Down Expand Up @@ -111,6 +112,12 @@ release:
python3 setup.py bdist_wheel && \
twine upload dist/*

# Usage:
# make pattern="tmp:*" delete-keys
.PHONY: delete-keys
delete-keys:
redis-cli --scan --pattern "$(pattern)" | xargs redis-cli del

.PHONY: clean
clean:
rm -rf {$(venv),pottery/__pycache__,tests/__pycache__,.coverage,.mypy_cache,pottery.egg-info,build,dist}
Expand Down
46 changes: 29 additions & 17 deletions pottery/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import time
from typing import ClassVar
from typing import Optional
from typing import Tuple
from typing import cast

from redis import WatchError
Expand All @@ -35,7 +36,11 @@ class RedisSimpleQueue(Base):
RETRY_DELAY: ClassVar[int] = 200

def qsize(self) -> int:
'Return the approximate size of the queue (not reliable!). O(1)'
'''Return the size of the queue. O(1)
Be aware that there's a potential race condition here where the queue
changes before you use the result of .qsize().
'''
return self.redis.xlen(self.key)

# Preserve the Open-Closed Principle with name mangling.
Expand All @@ -44,7 +49,13 @@ def qsize(self) -> int:
__qsize = qsize

def empty(self) -> bool:
'Return True if the queue is empty, False otherwise (not reliable!). O(1)'
'''Return True if the queue is empty; False otherwise. O(1)
This method is likely to be removed at some point. Use `.qsize() == 0`
as a direct substitute, but be aware that either approach risks a race
condition where the queue grows before you use the result of .empty() or
.qsize().
'''
return self.__qsize() == 0

def put(self,
Expand All @@ -54,7 +65,7 @@ def put(self,
) -> None:
'''Put the item on the queue. O(1)
The optional 'block' and 'timeout' arguments are ignored, as this method
The optional block and timeout arguments are ignored, as this method
never blocks. They are provided for compatibility with the queue.Queue
class.
'''
Expand All @@ -66,24 +77,23 @@ def put(self,
def put_nowait(self, item: JSONTypes) -> None:
'''Put an item into the queue without blocking. O(1)
This is exactly equivalent to `.put(item)` and is only provided for
This is exactly equivalent to `.put(item)` and is provided for
compatibility with the queue.Queue class.
'''
return self.__put(item, False)
return self.__put(item, block=False)

def get(self,
block: bool = True,
timeout: Optional[float] = None,
) -> JSONTypes:
'''Remove and return an item from the queue. O(1)
If optional args 'block' is true and 'timeout' is None (the default),
block if necessary until an item is available. If 'timeout' is
a non-negative number, it blocks at most 'timeout' seconds and raises
the Empty exception if no item was available within that time.
Otherwise ('block' is false), return an item if one is immediately
available, else raise the QueueEmptyError exception ('timeout' is
ignored in that case).
If optional args block is True and timeout is None (the default), block
if necessary until an item is available. If timeout is a non-negative
number, block at most timeout seconds and raise the QueueEmptyError
exception if no item becomes available within that time. Otherwise
(block is False), return an item if one is immediately available, else
raise the QueueEmptyError exception (timeout is ignored in this case).
'''
redis_block = (timeout or 0.0) if block else 0.0
redis_block = math.floor(redis_block)
Expand All @@ -108,8 +118,7 @@ def __remove_and_return(self, redis_block: int) -> JSONTypes:
returned_value = pipeline.xread({self.key: 0}, count=1, block=redis_block)
# The following line raises IndexError if the RedisQueue is empty
# and we're blocking.
id_ = cast(bytes, returned_value[0][1][0][0])
dict_ = cast(dict, returned_value[0][1][0][1])
id_, dict_ = cast(Tuple[bytes, dict], returned_value[0][1][0])
pipeline.multi()
pipeline.xdel(self.key, id_)
encoded_value = dict_[b'item']
Expand All @@ -119,7 +128,10 @@ def __remove_and_return(self, redis_block: int) -> JSONTypes:
def get_nowait(self) -> JSONTypes:
'''Remove and return an item from the queue without blocking. O(1)
Only get an item if one is immediately available. Otherwise
raise the Empty exception.
Get an item if one is immediately available. Otherwise raise the
QueueEmptyError exception.
This is exactly equivalent to `.get(block=False)` and is provided for
compatibility with the queue.Queue class.
'''
return self.__get(False)
return self.__get(block=False)

0 comments on commit 687d41a

Please sign in to comment.