Replace retrying with tenacity

Change-Id: I1f4710ac0b7a3fd32cd3406254ecbd6b7ae1dfa2
Closes-Bug: #1635406
This commit is contained in:
Julien Danjou 2016-11-10 13:44:16 +01:00
parent 6286b40eae
commit 533341aebb
7 changed files with 27 additions and 72 deletions

View File

@ -8,7 +8,7 @@ enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' #
voluptuous>=0.8.9 # BSD License
msgpack-python>=0.4.0 # Apache-2.0
fasteners>=0.7 # Apache-2.0
retrying!=1.3.0,>=1.2.3 # Apache-2.0
tenacity>=3.2.1 # Apache-2.0
futures>=3.0;python_version=='2.7' or python_version=='2.6' # BSD
futurist!=0.15.0,>=0.11.0 # Apache-2.0
oslo.utils>=3.15.0 # Apache-2.0

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2014 eNovance
# Copyright © 2016 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
@ -13,30 +13,19 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import retrying
import tenacity
from tenacity import stop
from tenacity import wait
class Retry(Exception):
"""Exception raised if we need to retry."""
_default_wait = wait.wait_exponential(max=1)
def retry_if_retry_raised(exception):
return isinstance(exception, Retry)
def retry(stop_max_delay=None, **kwargs):
k = {"wait": _default_wait, "retry": lambda x: False}
if stop_max_delay not in (True, False, None):
k['stop'] = stop.stop_after_delay(stop_max_delay)
return tenacity.retry(**k)
RETRYING_KWARGS = dict(
retry_on_exception=retry_if_retry_raised,
wait='exponential_sleep',
wait_exponential_max=1,
)
def retry(**kwargs):
delay = kwargs.get('stop_max_delay', None)
kwargs['stop_max_delay'] = delay if delay not in (True, False) else None
k = RETRYING_KWARGS.copy()
k.update(kwargs)
return retrying.retry(**k)
Retrying = retrying.Retrying
TryAgain = tenacity.TryAgain

View File

@ -48,7 +48,7 @@ class ConsulLock(locking.Lock):
if blocking is False:
return False
else:
raise _retry.Retry
raise _retry.TryAgain
else:
# The value can be anything.
gotten = self._client.kv.put(key=self._name,
@ -60,7 +60,7 @@ class ConsulLock(locking.Lock):
if blocking is False:
return False
else:
raise _retry.Retry
raise _retry.TryAgain
return _acquire()

View File

@ -97,7 +97,7 @@ class MemcachedLock(locking.Lock):
return True
if blocking is False:
return False
raise _retry.Retry
raise _retry.TryAgain
return _acquire()
@ -310,12 +310,12 @@ class MemcachedDriver(coordination._RunWatchersMixin,
if not self.client.cas(self.GROUP_LIST_KEY,
list(group_list), cas):
# Someone updated the group list before us, try again!
raise _retry.Retry
raise _retry.TryAgain
else:
if not self.client.add(self.GROUP_LIST_KEY,
[group_id], noreply=False):
# Someone updated the group list before us, try again!
raise _retry.Retry
raise _retry.TryAgain
@_retry.retry()
def _remove_from_group_list(self, group_id):
@ -329,7 +329,7 @@ class MemcachedDriver(coordination._RunWatchersMixin,
if not self.client.cas(self.GROUP_LIST_KEY,
list(group_list), cas):
# Someone updated the group list before us, try again!
raise _retry.Retry
raise _retry.TryAgain
def create_group(self, group_id):
encoded_group = self._encode_group_id(group_id)
@ -367,7 +367,7 @@ class MemcachedDriver(coordination._RunWatchersMixin,
}
if not self.client.cas(encoded_group, group_members, cas):
# It changed, let's try again
raise _retry.Retry
raise _retry.TryAgain
self._joined_groups.add(group_id)
return MemcachedFutureResult(self._executor.submit(_join_group))
@ -386,7 +386,7 @@ class MemcachedDriver(coordination._RunWatchersMixin,
del group_members[self._member_id]
if not self.client.cas(encoded_group, group_members, cas):
# It changed, let's try again
raise _retry.Retry
raise _retry.TryAgain
self._joined_groups.discard(group_id)
return MemcachedFutureResult(self._executor.submit(_leave_group))
@ -408,7 +408,7 @@ class MemcachedDriver(coordination._RunWatchersMixin,
# Delete is not atomic, so we first set the group to
# using CAS, and then we delete it, to avoid race conditions.
if not self.client.cas(encoded_group, None, cas):
raise _retry.Retry
raise _retry.TryAgain
self.client.delete(encoded_group)
self._remove_from_group_list(group_id)
@ -431,7 +431,7 @@ class MemcachedDriver(coordination._RunWatchersMixin,
# There are some dead members, update the group
if not self.client.cas(encoded_group, actual_group_members, cas):
# It changed, let's try again
raise _retry.Retry
raise _retry.TryAgain
return actual_group_members
def get_members(self, group_id):
@ -466,7 +466,7 @@ class MemcachedDriver(coordination._RunWatchersMixin,
group_members[self._member_id][b'capabilities'] = capabilities
if not self.client.cas(encoded_group, group_members, cas):
# It changed, try again
raise _retry.Retry
raise _retry.TryAgain
return MemcachedFutureResult(
self._executor.submit(_update_capabilities))

View File

@ -52,7 +52,7 @@ class MySQLLock(locking.Lock):
# So, we track locally the lock status with self.acquired
if self.acquired is True:
if blocking:
raise _retry.Retry
raise _retry.TryAgain
return False
try:
@ -69,7 +69,7 @@ class MySQLLock(locking.Lock):
cause=e)
if blocking:
raise _retry.Retry
raise _retry.TryAgain
return False
return _lock()

View File

@ -112,7 +112,7 @@ class PostgresLock(locking.Lock):
# so we track it internally if the process already has the lock.
if self.acquired is True:
if blocking:
raise _retry.Retry
raise _retry.TryAgain
return False
with _translating_cursor(self._conn) as cur:
@ -130,7 +130,7 @@ class PostgresLock(locking.Lock):
elif blocking is False:
return False
else:
raise _retry.Retry
raise _retry.TryAgain
return _lock()

View File

@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2014 eNovance
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from testtools import testcase
from tooz.drivers import _retry
class TestRetry(testcase.TestCase):
def test_retry(self):
self.i = 1
@_retry.retry()
def x(add_that):
if self.i == 1:
self.i += add_that
raise _retry.Retry
return self.i
self.assertEqual(x(42), 43)