Skip to content

Instantly share code, notes, and snippets.

@kernel0
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kernel0/7bf57e6bc84719069cc9 to your computer and use it in GitHub Desktop.
Save kernel0/7bf57e6bc84719069cc9 to your computer and use it in GitHub Desktop.
issue : pool reallocates non-free connection whenever use multi method
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
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
@kernel0
Copy link
Author

kernel0 commented Mar 5, 2015

  1. One task calls "pool.multi" method
  2. "pool.multi" method uses "_get_free_connection()"
  3. "_get_free_connection" method reads "self.in_transaction" in protocol's "in_use" property.
  4. Because "self.in_transaction" is False, return connection and call "multi" method in "protocol.py"
  5. When execute line number 16 in above "asyncio_redis.protocol.py", issue context switching.
  6. Another task calls "pool.multi" method
  7. "pool.multi" method uses "_get_free_connection"
  8. "_get_free_connection" method reads "self.in_transaction" in protocol's "in_use" property.
  9. Because "self.in_transaction" is still False, return same connection and call "multi" method in "protocol.py"
  10. 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