Mark quota operations as retriable
This decorates the quota system operations with the retry decorators. This will help significantly with the bug this marks as closed since operations in the quota engine after commit should no longer trigger retries of the full API operation. The logic to find the args in the decorator had to be adjusted to deal with functions already decorated. This just uses the getargspec function from pecan that deals with decorated functions. Partial-Bug: #1612798 Closes-Bug: #1596075 Change-Id: Ib786117dcea08af75551770ea4c30d460382b829
This commit is contained in:
parent
ad13bdfa27
commit
12420c1585
@ -26,6 +26,7 @@ from oslo_db.sqlalchemy import enginefacade
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
import osprofiler.sqlalchemy
|
||||
from pecan import util as p_util
|
||||
import six
|
||||
import sqlalchemy
|
||||
from sqlalchemy.orm import exc
|
||||
@ -137,7 +138,10 @@ def retry_if_session_inactive(context_var_name='context'):
|
||||
"""
|
||||
def decorator(f):
|
||||
try:
|
||||
ctx_arg_index = f.__code__.co_varnames.index(context_var_name)
|
||||
# NOTE(kevinbenton): we use pecan's util function here because it
|
||||
# deals with the horrors of finding args of already decorated
|
||||
# functions
|
||||
ctx_arg_index = p_util.getargspec(f).args.index(context_var_name)
|
||||
except ValueError:
|
||||
raise RuntimeError(_LE("Could not find position of var %s")
|
||||
% context_var_name)
|
||||
|
@ -40,6 +40,7 @@ class ReservationInfo(collections.namedtuple(
|
||||
"""Information about a resource reservation."""
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def get_quota_usage_by_resource_and_tenant(context, resource, tenant_id,
|
||||
lock_for_update=False):
|
||||
"""Return usage info for a given resource and tenant.
|
||||
@ -66,6 +67,7 @@ def get_quota_usage_by_resource_and_tenant(context, resource, tenant_id,
|
||||
result.dirty)
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def get_quota_usage_by_resource(context, resource):
|
||||
query = common_db_api.model_query(context, quota_models.QuotaUsage)
|
||||
query = query.filter_by(resource=resource)
|
||||
@ -75,6 +77,7 @@ def get_quota_usage_by_resource(context, resource):
|
||||
item.dirty) for item in query]
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def get_quota_usage_by_tenant_id(context, tenant_id):
|
||||
query = common_db_api.model_query(context, quota_models.QuotaUsage)
|
||||
query = query.filter_by(tenant_id=tenant_id)
|
||||
@ -84,6 +87,7 @@ def get_quota_usage_by_tenant_id(context, tenant_id):
|
||||
item.dirty) for item in query]
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def set_quota_usage(context, resource, tenant_id,
|
||||
in_use=None, delta=False):
|
||||
"""Set resource quota usage.
|
||||
@ -121,6 +125,7 @@ def set_quota_usage(context, resource, tenant_id,
|
||||
usage_data.dirty)
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
@db_api.context_manager.writer
|
||||
def set_quota_usage_dirty(context, resource, tenant_id, dirty=True):
|
||||
"""Set quota usage dirty bit for a given resource and tenant.
|
||||
@ -135,6 +140,7 @@ def set_quota_usage_dirty(context, resource, tenant_id, dirty=True):
|
||||
return query.update({'dirty': dirty})
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
@db_api.context_manager.writer
|
||||
def set_resources_quota_usage_dirty(context, resources, tenant_id, dirty=True):
|
||||
"""Set quota usage dirty bit for a given tenant and multiple resources.
|
||||
@ -153,6 +159,7 @@ def set_resources_quota_usage_dirty(context, resources, tenant_id, dirty=True):
|
||||
return query.update({'dirty': dirty}, synchronize_session=False)
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
@db_api.context_manager.writer
|
||||
def set_all_quota_usage_dirty(context, resource, dirty=True):
|
||||
"""Set the dirty bit on quota usage for all tenants.
|
||||
@ -166,6 +173,7 @@ def set_all_quota_usage_dirty(context, resource, dirty=True):
|
||||
return query.update({'dirty': dirty})
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def create_reservation(context, tenant_id, deltas, expiration=None):
|
||||
# This method is usually called from within another transaction.
|
||||
# Consider using begin_nested
|
||||
@ -186,6 +194,7 @@ def create_reservation(context, tenant_id, deltas, expiration=None):
|
||||
for delta in resv.resource_deltas))
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def get_reservation(context, reservation_id):
|
||||
query = context.session.query(quota_models.Reservation).filter_by(
|
||||
id=reservation_id)
|
||||
@ -199,6 +208,7 @@ def get_reservation(context, reservation_id):
|
||||
for delta in resv.resource_deltas))
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
@db_api.context_manager.writer
|
||||
def remove_reservation(context, reservation_id, set_dirty=False):
|
||||
delete_query = context.session.query(quota_models.Reservation).filter_by(
|
||||
@ -220,6 +230,7 @@ def remove_reservation(context, reservation_id, set_dirty=False):
|
||||
return num_deleted
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def get_reservations_for_resources(context, tenant_id, resources,
|
||||
expired=False):
|
||||
"""Retrieve total amount of reservations for specified resources.
|
||||
@ -254,6 +265,7 @@ def get_reservations_for_resources(context, tenant_id, resources,
|
||||
for (resource, exp, total_reserved) in resv_query)
|
||||
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
@db_api.context_manager.writer
|
||||
def remove_expired_reservations(context, tenant_id=None):
|
||||
now = utcnow()
|
||||
|
@ -49,6 +49,7 @@ class DbQuotaDriver(object):
|
||||
for key, resource in resources.items())
|
||||
|
||||
@staticmethod
|
||||
@db_api.retry_if_session_inactive()
|
||||
def get_tenant_quotas(context, resources, tenant_id):
|
||||
"""Given a list of resources, retrieve the quotas for the given
|
||||
tenant. If no limits are found for the specified tenant, the operation
|
||||
@ -73,6 +74,7 @@ class DbQuotaDriver(object):
|
||||
return tenant_quota
|
||||
|
||||
@staticmethod
|
||||
@db_api.retry_if_session_inactive()
|
||||
def delete_tenant_quota(context, tenant_id):
|
||||
"""Delete the quota entries for a given tenant_id.
|
||||
|
||||
@ -88,6 +90,7 @@ class DbQuotaDriver(object):
|
||||
raise n_exc.TenantQuotaNotFound(tenant_id=tenant_id)
|
||||
|
||||
@staticmethod
|
||||
@db_api.retry_if_session_inactive()
|
||||
def get_all_quotas(context, resources):
|
||||
"""Given a list of resources, retrieve the quotas for the all tenants.
|
||||
|
||||
@ -119,6 +122,7 @@ class DbQuotaDriver(object):
|
||||
return list(all_tenant_quotas.values())
|
||||
|
||||
@staticmethod
|
||||
@db_api.retry_if_session_inactive()
|
||||
def update_quota_limit(context, tenant_id, resource, limit):
|
||||
with context.session.begin():
|
||||
tenant_quota = context.session.query(quota_models.Quota).filter_by(
|
||||
@ -156,7 +160,7 @@ class DbQuotaDriver(object):
|
||||
quota_api.remove_expired_reservations(
|
||||
context, tenant_id=tenant_id)
|
||||
|
||||
@db_api.retry_db_errors
|
||||
@db_api.retry_if_session_inactive()
|
||||
def make_reservation(self, context, tenant_id, resources, deltas, plugin):
|
||||
# Lock current reservation table
|
||||
# NOTE(salv-orlando): This routine uses DB write locks.
|
||||
|
@ -207,7 +207,7 @@ class TrackedResource(BaseResource):
|
||||
# can happen is two or more workers are trying to create a resource of a
|
||||
# give kind for the same tenant concurrently. Retrying the operation will
|
||||
# ensure that an UPDATE statement is emitted rather than an INSERT one
|
||||
@db_api.retry_db_errors
|
||||
@db_api.retry_if_session_inactive()
|
||||
def _set_quota_usage(self, context, tenant_id, in_use):
|
||||
return quota_api.set_quota_usage(
|
||||
context, self.name, tenant_id, in_use=in_use)
|
||||
|
Loading…
Reference in New Issue
Block a user