Add retry for DBDeadlock in credential delete
Adds oslo.db retry wrapper to delete_credential_for_user method. Change-Id: Ib9e161411f0985785eec46c51d721ef7421ee090 Closes-Bug: #1840291
This commit is contained in:
parent
5beddfaddb
commit
e989bd0637
@ -12,6 +12,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_db import api as oslo_db_api
|
||||
|
||||
from keystone.common import driver_hints
|
||||
from keystone.common import sql
|
||||
from keystone.credential.backends import base
|
||||
@ -96,6 +98,7 @@ class Credential(base.CredentialDriverBase):
|
||||
query = query.filter_by(project_id=project_id)
|
||||
query.delete()
|
||||
|
||||
@oslo_db_api.wrap_db_retry(retry_on_deadlock=True)
|
||||
def delete_credentials_for_user(self, user_id):
|
||||
with sql.session_for_write() as session:
|
||||
query = session.query(CredentialModel)
|
||||
|
@ -17,6 +17,8 @@ import json
|
||||
import uuid
|
||||
|
||||
from keystoneclient.contrib.ec2 import utils as ec2_utils
|
||||
import mock
|
||||
from oslo_db import exception as oslo_db_exception
|
||||
from six.moves import http_client
|
||||
from testtools import matchers
|
||||
|
||||
@ -262,6 +264,38 @@ class CredentialTestCase(CredentialBaseTestCase):
|
||||
'/credentials/%(credential_id)s' % {
|
||||
'credential_id': self.credential['id']})
|
||||
|
||||
def test_delete_credential_retries_on_deadlock(self):
|
||||
patcher = mock.patch('sqlalchemy.orm.query.Query.delete',
|
||||
autospec=True)
|
||||
|
||||
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:
|
||||
PROVIDERS.credential_api.delete_credentials_for_user(
|
||||
user_id=self.user['id'])
|
||||
finally:
|
||||
if side_effect.patched:
|
||||
patcher.stop()
|
||||
|
||||
# initial attempt + 1 retry
|
||||
self.assertEqual(sql_delete_mock.call_count, 2)
|
||||
|
||||
def test_create_ec2_credential(self):
|
||||
"""Call ``POST /credentials`` for creating ec2 credential."""
|
||||
blob, ref = unit.new_ec2_credential(user_id=self.user['id'],
|
||||
|
6
releasenotes/notes/bug-1840291-35af1ac7ba06e166.yaml
Normal file
6
releasenotes/notes/bug-1840291-35af1ac7ba06e166.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
[`bug 1840291 <https://bugs.launchpad.net/keystone/+bug/1840291>`_]
|
||||
Adds retries for ``delete_credential_for_user`` method to avoid
|
||||
DBDeadlocks when deleting large number of credentials concurrently.
|
Loading…
Reference in New Issue
Block a user