Merge "Support query queues with count"

This commit is contained in:
Zuul 2020-01-17 05:16:27 +00:00 committed by Gerrit Code Review
commit ffd8b5621f
12 changed files with 86 additions and 6 deletions

View File

@ -151,6 +151,14 @@ pop:
``pop`` & ``ids`` parameters are mutually exclusive. Using them together ``pop`` & ``ids`` parameters are mutually exclusive. Using them together
in a request will result in HTTP 400. in a request will result in HTTP 400.
with_count:
type: boolean
in: query
required: false
description: |
The 'with_count' specifies if showing the amount of queues when querying
them.
# variables in body # variables in body
_dead_letter_queue: _dead_letter_queue:
@ -312,6 +320,13 @@ claim_ttl:
the claim. The ttl value must be between 60 and 43200 seconds (12 hours). the claim. The ttl value must be between 60 and 43200 seconds (12 hours).
You must include a value for this attribute in your request. You must include a value for this attribute in your request.
count:
type: integer
in: body
required: false
description: |
The ``count`` attribute specifies how many queus in current project.
flavor_href: flavor_href:
type: string type: string
in: body in: body

View File

@ -50,6 +50,7 @@ Request Parameters
- marker: marker - marker: marker
- detailed: detailed - detailed: detailed
- name: name - name: name
- with_count: with_count
Response Parameters Response Parameters
------------------- -------------------
@ -58,6 +59,7 @@ Response Parameters
- queues: queues - queues: queues
- links: links - links: links
- count: count
Response Example Response Example

View File

@ -18,5 +18,6 @@
"href":"/v2/queues?marker=wellington", "href":"/v2/queues?marker=wellington",
"rel":"next" "rel":"next"
} }
] ],
"count": 3
} }

View File

@ -0,0 +1,5 @@
---
features:
- Support query queues with filter 'with_count=true' to return the amount of
the queues. This will help users to quickly get the exact total number of
queues which they own.

View File

@ -418,6 +418,16 @@ class Queue(ControllerBase):
_stats = abc.abstractmethod(lambda x: None) _stats = abc.abstractmethod(lambda x: None)
def calculate_resource_count(self, project=None):
"""Base method for calculate queues amount.
:param project: Project id
:returns: The number of queues.
"""
return self._calculate_resource_count(project)
_calculate_resource_count = abc.abstractmethod(lambda x: None)
@six.add_metaclass(abc.ABCMeta) @six.add_metaclass(abc.ABCMeta)
class Message(ControllerBase): class Message(ControllerBase):

View File

@ -287,6 +287,13 @@ class QueueController(storage.Queue):
def _stats(self, name, project=None): def _stats(self, name, project=None):
pass pass
@utils.raises_conn_error
@utils.retries_on_autoreconnect
def _calculate_resource_count(self, project=None):
query = utils.scoped_query(None, project, None, {})
projection = {'p_q': 1, '_id': 0}
return self._collection.find(query, projection=projection).count()
def _get_scoped_query(name, project): def _get_scoped_query(name, project):
return {'p_q': utils.scope_queue_name(name, project)} return {'p_q': utils.scope_queue_name(name, project)}

View File

@ -264,6 +264,9 @@ class QueueController(storage.Queue):
return mqHandler.stats(name, project=project) return mqHandler.stats(name, project=project)
raise errors.QueueDoesNotExist(name, project) raise errors.QueueDoesNotExist(name, project)
def _calculate_resource_count(self, project=None):
return self._mgt_queue_ctrl.calculate_resource_count(project=project)
class MessageController(storage.Message): class MessageController(storage.Message):
"""Routes operations to a message controller in the appropriate pool. """Routes operations to a message controller in the appropriate pool.

View File

@ -103,7 +103,7 @@ class QueueController(storage.Queue):
queue = {'name': utils.descope_queue_name(name)} queue = {'name': utils.descope_queue_name(name)}
marker_next['next'] = queue['name'] marker_next['next'] = queue['name']
if detailed: if detailed:
queue['metadata'] = info[1] queue['metadata'] = self._unpacker(info[1])
return queue return queue
@ -192,3 +192,10 @@ class QueueController(storage.Queue):
@utils.retries_on_connection_error @utils.retries_on_connection_error
def _stats(self, name, project=None): def _stats(self, name, project=None):
pass pass
@utils.raises_conn_error
@utils.retries_on_connection_error
def _calculate_resource_count(self, project=None):
client = self._client
qset_key = utils.scope_queue_name(QUEUES_SET_STORE_NAME, project)
return client.zlexcount(qset_key, '-', '+')

View File

@ -134,3 +134,13 @@ class QueueController(storage.Queue):
def _stats(self, name, project): def _stats(self, name, project):
pass pass
def _calculate_resource_count(self, project=None):
if project is None:
project = ''
sel = sa.sql.select([sa.sql.func.count('*')],
tables.Queues.c.project == project)
res = self.driver.run(sel)
r = res.fetchone()
res.close()
return r is not None

View File

@ -123,6 +123,9 @@ class QueueController(storage.Queue):
def _stats(self, name, project=None): def _stats(self, name, project=None):
raise NotImplementedError() raise NotImplementedError()
def _calculate_resource_count(self, project=None):
raise NotImplementedError()
class MessageController(storage.Message): class MessageController(storage.Message):
def __init__(self, driver): def __init__(self, driver):

View File

@ -587,6 +587,13 @@ class TestQueueLifecycleMongoDB(base.V2Base):
result_doc = jsonutils.loads(result[0]) result_doc = jsonutils.loads(result[0])
self.assertEqual(3, len(result_doc['queues'])) self.assertEqual(3, len(result_doc['queues']))
# List (filter query)
result = self.simulate_get(self.queue_path, headers=header,
query_string='with_count=true')
result_doc = jsonutils.loads(result[0])
self.assertEqual(3, result_doc['count'])
class TestQueueLifecycleFaultyDriver(base.V2BaseFaulty): class TestQueueLifecycleFaultyDriver(base.V2BaseFaulty):

View File

@ -256,12 +256,17 @@ class CollectionResource(object):
def _queue_list(self, project_id, path, kfilter, **kwargs): def _queue_list(self, project_id, path, kfilter, **kwargs):
try: try:
self._validate.queue_listing(**kwargs) self._validate.queue_listing(**kwargs)
with_count = kwargs.pop('with_count', False)
results = self._queue_controller.list(project=project_id, results = self._queue_controller.list(project=project_id,
kfilter=kfilter, **kwargs) kfilter=kfilter, **kwargs)
# Buffer list of queues # Buffer list of queues
queues = list(next(results)) queues = list(next(results))
total_number = None
if with_count:
total_number = self._queue_controller.calculate_resource_count(
project=project_id)
except validation.ValidationFailed as ex: except validation.ValidationFailed as ex:
LOG.debug(ex) LOG.debug(ex)
raise wsgi_errors.HTTPBadRequestAPI(six.text_type(ex)) raise wsgi_errors.HTTPBadRequestAPI(six.text_type(ex))
@ -281,7 +286,7 @@ class CollectionResource(object):
if not each_queue.get('metadata', {}).get(meta): if not each_queue.get('metadata', {}).get(meta):
each_queue['metadata'][meta] = value each_queue['metadata'][meta] = value
return queues, kwargs['marker'] return queues, kwargs['marker'], total_number
def _on_get_with_kfilter(self, req, resp, project_id, kfilter={}): def _on_get_with_kfilter(self, req, resp, project_id, kfilter={}):
kwargs = {} kwargs = {}
@ -292,9 +297,11 @@ class CollectionResource(object):
req.get_param_as_int('limit', store=kwargs) req.get_param_as_int('limit', store=kwargs)
req.get_param_as_bool('detailed', store=kwargs) req.get_param_as_bool('detailed', store=kwargs)
req.get_param('name', store=kwargs) req.get_param('name', store=kwargs)
req.get_param_as_bool('with_count', store=kwargs)
queues, marker = self._queue_list(project_id, queues, marker, total_number = self._queue_list(project_id,
req.path, kfilter, **kwargs) req.path, kfilter,
**kwargs)
links = [] links = []
kwargs['marker'] = marker kwargs['marker'] = marker
@ -311,13 +318,16 @@ class CollectionResource(object):
'links': links 'links': links
} }
if total_number:
response_body['count'] = total_number
resp.body = utils.to_json(response_body) resp.body = utils.to_json(response_body)
# status defaults to 200 # status defaults to 200
@decorators.TransportLog("Queues collection") @decorators.TransportLog("Queues collection")
@acl.enforce("queues:get_all") @acl.enforce("queues:get_all")
def on_get(self, req, resp, project_id): def on_get(self, req, resp, project_id):
field = ('marker', 'limit', 'detailed', 'name') field = ('marker', 'limit', 'detailed', 'name', 'with_count')
kfilter = copy.deepcopy(req.params) kfilter = copy.deepcopy(req.params)
for key in req.params.keys(): for key in req.params.keys():