fix(storage/mongo): unclaimed messages not listed

Adds a unit test that reproduces this error and applies the fix.

The fix is subtle. When messages are unclaimed, their claim expiration
time and claim ID are set to 0 and None respectively. The cause for
the bug is that claim expiration time is set to 0, rather than a valid
datetime object. As a result, the comparison silently fails.

The fix: fast-forward the expiration time of a claim to now.

Change-Id: I7781795c394b2a471012e072a522ee228d56a894
Closes-Bug: #1210633
This commit is contained in:
Alejandro Cabrera 2013-08-12 14:31:55 -04:00
parent ae127035c5
commit ed40dfd17c
2 changed files with 25 additions and 1 deletions

View File

@ -373,8 +373,11 @@ class MessageController(storage.MessageBase):
except ValueError: except ValueError:
return return
# NOTE(cpp-cabrera): unclaim by setting the claim ID to None
# and the claim expiration time to now
now = timeutils.utcnow()
self._col.update({'q': queue_name, 'p': project, 'c.id': cid}, self._col.update({'q': queue_name, 'p': project, 'c.id': cid},
{'$set': {'c': {'id': None, 'e': 0}}}, {'$set': {'c': {'id': None, 'e': now}}},
upsert=False, multi=True) upsert=False, multi=True)
def remove_expired(self): def remove_expired(self):

View File

@ -311,6 +311,27 @@ class MessagesBaseTest(base.TestBase):
self.simulate_get(path, '7e7e7e') self.simulate_get(path, '7e7e7e')
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
# NOTE(cpp-cabrera): regression test against bug #1210633
def test_when_claim_deleted_then_messages_unclaimed(self):
path = self.queue_path
self._post_messages(path + '/messages', repeat=5)
# post claim
self.simulate_post(path + '/claims', self.project_id,
body='{"ttl": 100, "grace": 100}')
self.assertEquals(self.srmock.status, falcon.HTTP_201)
location = self.srmock.headers_dict['Location']
# release claim
self.simulate_delete(location, self.project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_204)
# get unclaimed messages
self.simulate_get(path + '/messages', self.project_id,
query_string='echo=true',
headers=self.headers)
self.assertEquals(self.srmock.status, falcon.HTTP_200)
def _post_messages(self, target, repeat=1): def _post_messages(self, target, repeat=1):
doc = json.dumps([{'body': 239, 'ttl': 300}] * repeat) doc = json.dumps([{'body': 239, 'ttl': 300}] * repeat)
self.simulate_post(target, self.project_id, body=doc, self.simulate_post(target, self.project_id, body=doc,