Skip to content

Commit

Permalink
Merge pull request #100 from yahoo/race_condition_fix
Browse files Browse the repository at this point in the history
Deal with the server being busy when it is starting up.
  • Loading branch information
dwighthubbard committed Apr 27, 2016
2 parents 7a19b9f + 53afcd5 commit b3c8f1b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
28 changes: 26 additions & 2 deletions redislite/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def _connection_count(self):
for client in self.client_list():
flags = client.get('flags', '')
flags = flags.upper()
if 'U' in flags or 'N' in flags:
if 'U' in flags or 'N' in flags: # pragma: no cover
active_connections += 1
return active_connections

Expand Down Expand Up @@ -200,9 +200,33 @@ def _start_redis(self):
raise RedisLiteException(
'Redis socket file %s is not present' % self.socket_file
)

self._save_setting_registry()
self.running = True

def _wait_for_server_start(self):
"""
Wait until the server is not busy when receiving a request
Raises
------
RedisLiteServerStartError - Server start timed out
"""
timeout = True
for i in range(0, self.start_timeout * 10):
try:
self.ping()
timeout = False
break
except redis.BusyLoadingError:
pass
time.sleep(.1)
if timeout: # pragma: no cover
raise RedisLiteServerStartError(
'The redis-server process failed to start; unreachable after '
'{0} seconds'.format(self.start_timeout)
)

def _is_redis_running(self):
"""
Determine if there is a config setting for a currently running redis
Expand Down Expand Up @@ -367,7 +391,7 @@ def __init__(self, *args, **kwargs):
super(RedisMixin, self).__init__(*args, **kwargs) # pragma: no cover

logger.debug("Pinging the server to ensure we're connected")
self.ping()
self._wait_for_server_start()

def __del__(self):
self._cleanup() # pragma: no cover
Expand Down
17 changes: 17 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,23 @@ def test_connection_fallthrough(self):
with self.assertRaises(ConnectionError):
redislite.Redis(port=1).keys()

def test_shutdown_race_condition(self):
"""
Test that there is no race condition when a shutdown is run after
a large data operation.
"""
if os.path.exists('bug.redis'):
os.remove('bug.redis')
db = redislite.StrictRedis('bug.redis')
for key in range(10000):
db.hset("h1", os.urandom(32), " " * 65536)
db.save()
db._cleanup()
del db
db = redislite.StrictRedis('bug.redis')
if os.path.exists('bug.redis'):
os.remove('bug.redis')


if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
Expand Down

0 comments on commit b3c8f1b

Please sign in to comment.