feat(api): GET and HEAD methods on queue

To allow

    GET/HEAD /queues/a-queue

gives users an intuitive approach to test whether the queue exits,
while the URI above is returned as the Location header by a queue's
PUT method.

Implements: blueprint queue-get-and-head
Fixes: bug #1207075

Change-Id: Iefd3236a739b1a5d959efb489fc2b966ee893599
This commit is contained in:
Zhihao Yuan 2013-08-06 10:54:46 -04:00
parent 5b1c447ba2
commit 47e3638f95
7 changed files with 56 additions and 4 deletions

View File

@ -113,7 +113,7 @@ class QueueBase(ControllerBase):
@abc.abstractmethod
def create(self, name, project=None):
"""Base method for queue creation
"""Base method for queue creation.
:param name: The queue name
:param project: Project id
@ -122,6 +122,17 @@ class QueueBase(ControllerBase):
"""
raise NotImplementedError
@abc.abstractmethod
def exists(self, name, project=None):
"""Base method for testing queue existence.
:param name: The queue name
:param project: Project id
:returns: True if a queue exists and False
if it does not.
"""
raise NotImplementedError
@abc.abstractmethod
def set_metadata(self, name, metadata, project=None):
"""Base method for updating a queue metadata.

View File

@ -122,6 +122,10 @@ class QueueController(storage.QueueBase):
else:
return True
@utils.raises_conn_error
def exists(self, name, project=None):
return self._col.find_one({'p': project, 'n': name}) is not None
@utils.raises_conn_error
def set_metadata(self, name, metadata, project=None):
rst = self._col.update({'p': project, 'n': name},

View File

@ -95,6 +95,15 @@ class QueueController(base.QueueBase):
return self.driver.affected
def exists(self, name, project):
if project is None:
project = ''
return self.driver.run('''
select id from Queues
where project = ? and name = ?
''', project, name).fetchone() is not None
def set_metadata(self, name, metadata, project):
if project is None:
project = ''

View File

@ -75,6 +75,9 @@ class QueueControllerTest(ControllerBaseTest):
created = self.controller.create('test', project=self.project)
self.assertTrue(created)
# Test Queue Existence
self.assertTrue(self.controller.exists('test', project=self.project))
# Test Queue retrieval
metadata = self.controller.get_metadata('test', project=self.project)
self.assertEqual(metadata, {})
@ -103,6 +106,9 @@ class QueueControllerTest(ControllerBaseTest):
# Test Queue Deletion
self.controller.delete('test', project=self.project)
# Test Queue Existence
self.assertFalse(self.controller.exists('test', project=self.project))
# Test DoesNotExist Exception
with testing.expect(storage.exceptions.DoesNotExist):
self.controller.get_metadata('test', project=self.project)

View File

@ -48,9 +48,9 @@ class QueueLifecycleBaseTest(base.TestBase):
location = ('Location', '/v1/queues/gumshoe')
self.assertIn(location, self.srmock.headers)
# Get on queues shouldn't work any more
self.simulate_get(path, project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_405)
# Ensure queue existence
self.simulate_head(path, project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_204)
# Add metadata
doc = '{"messages": {"ttl": 600}}'
@ -67,6 +67,10 @@ class QueueLifecycleBaseTest(base.TestBase):
self.simulate_delete(path, project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_204)
# Get non-existent queue
self.simulate_get(path, project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_404)
# Get non-existent stats
self.simulate_get(path + '/stats', project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_404)

View File

@ -44,6 +44,9 @@ class QueueController(storage.QueueBase):
def create(self, name, project=None):
raise NotImplementedError()
def exists(self, name, project=None):
raise NotImplementedError()
def set_metadata(self, name, metadata, project=None):
raise NotImplementedError()

View File

@ -49,6 +49,21 @@ class ItemResource(object):
resp.status = falcon.HTTP_201 if created else falcon.HTTP_204
resp.location = req.path
def on_head(self, req, resp, project_id, queue_name):
LOG.debug(_("Queue item exists - queue: %(queue)s, "
"project: %(project)s") %
{"queue": queue_name, "project": project_id})
if self.queue_controller.exists(queue_name,
project=project_id):
resp.status = falcon.HTTP_204
else:
resp.status = falcon.HTTP_404
resp.content_location = req.path
on_get = on_head
def on_delete(self, req, resp, project_id, queue_name):
LOG.debug(_("Queue item DELETE - queue: %(queue)s, "
"project: %(project)s") %