Merge "Separate exception class for retriables in callbacks"

This commit is contained in:
Jenkins 2016-06-23 18:12:44 +00:00 committed by Gerrit Code Review
commit 53d9e05def
3 changed files with 29 additions and 0 deletions

View File

@ -18,6 +18,7 @@ from oslo_utils import reflection
from neutron._i18n import _LE
from neutron.callbacks import events
from neutron.callbacks import exceptions
from neutron.db import api as db_api
LOG = logging.getLogger(__name__)
@ -106,6 +107,7 @@ class CallbacksManager(object):
del self._callbacks[resource][event][callback_id]
del self._index[callback_id]
@db_api.reraise_as_retryrequest
def notify(self, resource, event, trigger, **kwargs):
"""Notify all subscribed callback(s).

View File

@ -22,6 +22,7 @@ from oslo_db import exception as db_exc
from oslo_db.sqlalchemy import enginefacade
from oslo_utils import excutils
import osprofiler.sqlalchemy
import six
import sqlalchemy
from sqlalchemy.orm import exc
@ -55,6 +56,21 @@ retry_db_errors = oslo_db_api.wrap_db_retry(
)
def reraise_as_retryrequest(f):
"""Packs retriable exceptions into a RetryRequest."""
@six.wraps(f)
def wrapped(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
with excutils.save_and_reraise_exception() as ctx:
if is_retriable(e):
ctx.reraise = False
raise db_exc.RetryRequest(e)
return wrapped
def _is_nested_instance(e, etypes):
"""Check if exception or its inner excepts are an instance of etypes."""
return (isinstance(e, etypes) or

View File

@ -13,6 +13,7 @@
# under the License.
import mock
from oslo_db import exception as db_exc
from neutron.callbacks import events
from neutron.callbacks import exceptions
@ -35,6 +36,10 @@ def callback_raise(*args, **kwargs):
raise Exception()
def callback_raise_retriable(*args, **kwargs):
raise db_exc.DBDeadlock()
class CallBacksManagerTestCase(base.BaseTestCase):
def setUp(self):
@ -173,6 +178,12 @@ class CallBacksManagerTestCase(base.BaseTestCase):
resources.PORT, events.BEFORE_CREATE, self)
self.assertIsInstance(e.errors[0], exceptions.NotificationError)
def test_notify_handle_retriable_exception(self):
self.manager.subscribe(
callback_raise_retriable, resources.PORT, events.BEFORE_CREATE)
self.assertRaises(db_exc.RetryRequest, self.manager.notify,
resources.PORT, events.BEFORE_CREATE, self)
def test_notify_called_once_with_no_failures(self):
with mock.patch.object(self.manager, '_notify_loop') as n:
n.return_value = False