Retry revocation on MySQL deadlock
Added wrapper for revoke method that makes additional attempts on deadlock. Change-Id: I506c6b432d4d23619237a32414d0039c749cd8b6 Closes-Bug: #1604862
This commit is contained in:
parent
96af93d361
commit
e8022f3d31
|
@ -14,6 +14,8 @@ from keystone.common import sql
|
|||
from keystone.models import revoke_model
|
||||
from keystone.revoke.backends import base
|
||||
|
||||
from oslo_db import api as oslo_db_api
|
||||
|
||||
|
||||
class RevocationEvent(sql.ModelBase, sql.ModelDictMixin):
|
||||
__tablename__ = 'revocation_event'
|
||||
|
@ -90,6 +92,7 @@ class Revoke(base.RevokeDriverV8):
|
|||
|
||||
return events
|
||||
|
||||
@oslo_db_api.wrap_db_retry(retry_on_deadlock=True)
|
||||
def revoke(self, event):
|
||||
kwargs = dict()
|
||||
for attr in revoke_model.REVOKE_KEYS:
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
# under the License.
|
||||
|
||||
import datetime
|
||||
import mock
|
||||
import uuid
|
||||
|
||||
import freezegun
|
||||
from oslo_db import exception as oslo_db_exception
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
from six.moves import http_client
|
||||
|
@ -165,3 +167,41 @@ class OSRevokeTests(test_v3.RestfulTestCase, test_v3.JsonHomeTestMixin):
|
|||
# `OS-OAUTH1:access_token_id` is None and won't be returned to
|
||||
# end user.
|
||||
self.assertNotIn('OS-OAUTH1:access_token_id', event)
|
||||
|
||||
def test_retries_on_deadlock(self):
|
||||
patcher = mock.patch('sqlalchemy.orm.query.Query.delete',
|
||||
autospec=True)
|
||||
|
||||
# NOTE(mnikolaenko): raise 2 deadlocks and back to normal work of
|
||||
# method. Two attempts is enough to check that retry decorator works.
|
||||
# Otherwise it will take very much time to pass this test
|
||||
class FakeDeadlock(object):
|
||||
def __init__(self, mock_patcher):
|
||||
self.deadlock_count = 2
|
||||
self.mock_patcher = mock_patcher
|
||||
self.patched = True
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if self.deadlock_count > 1:
|
||||
self.deadlock_count -= 1
|
||||
else:
|
||||
self.mock_patcher.stop()
|
||||
self.patched = False
|
||||
raise oslo_db_exception.DBDeadlock
|
||||
|
||||
sql_delete_mock = patcher.start()
|
||||
side_effect = FakeDeadlock(patcher)
|
||||
sql_delete_mock.side_effect = side_effect
|
||||
|
||||
try:
|
||||
self.revoke_api.revoke(revoke_model.RevokeEvent(
|
||||
user_id=uuid.uuid4().hex))
|
||||
finally:
|
||||
if side_effect.patched:
|
||||
patcher.stop()
|
||||
|
||||
call_count = sql_delete_mock.call_count
|
||||
|
||||
# initial attempt + 1 retry
|
||||
revoke_attempt_count = 2
|
||||
self.assertEqual(call_count, revoke_attempt_count)
|
||||
|
|
Loading…
Reference in New Issue