Last active
August 29, 2015 14:16
-
-
Save kernel0/7bf57e6bc84719069cc9 to your computer and use it in GitHub Desktop.
issue : pool reallocates non-free connection whenever use multi method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _get_free_connection(self): | |
""" | |
Return the next protocol instance that's not in use. | |
(A protocol in pubsub mode or doing a blocking request is considered busy, | |
and can't be used for anything else.) | |
""" | |
self._shuffle_connections() | |
for c in self._connections: | |
if c.protocol.is_connected and not c.protocol.in_use: | |
return c | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
asyncio_redis.protocol.py | |
@asyncio.coroutine | |
def multi(self, watch:(ListOf(NativeType),NoneType)=None) -> 'Transaction': | |
if (self._in_transaction): | |
raise Error('Multi calls can not be nested.') | |
# Call watch | |
if watch is not None: | |
for k in watch: | |
result = yield from self._query(b'watch', self.encode_from_native(k)) | |
assert result == b'OK' | |
# Call multi | |
result = yield from self._query(b'multi') | |
assert result == b'OK' | |
self._in_transaction = True | |
self._transaction_response_queue = deque() | |
# Create transaction object. | |
t = Transaction(self) | |
self._transaction = t | |
return t | |
@property | |
def in_use(self): | |
""" True when this protocol is in use. """ | |
return self.in_blocking_call or self.in_pubsub or self.in_transaction |
Author
kernel0
commented
Mar 5, 2015
- One task calls "pool.multi" method
- "pool.multi" method uses "_get_free_connection()"
- "_get_free_connection" method reads "self.in_transaction" in protocol's "in_use" property.
- Because "self.in_transaction" is False, return connection and call "multi" method in "protocol.py"
- When execute line number 16 in above "asyncio_redis.protocol.py", issue context switching.
- Another task calls "pool.multi" method
- "pool.multi" method uses "_get_free_connection"
- "_get_free_connection" method reads "self.in_transaction" in protocol's "in_use" property.
- Because "self.in_transaction" is still False, return same connection and call "multi" method in "protocol.py"
- Redis server issues error "MULTI calls cannot be nested". It is not executing line number 7 of above "asyncio_redis.protocol.py" but replying server error.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment