Show 'age' field in subscriptions (mongodb)

We recently fixed subscriptions and now they are expirable resources as
they should be.
But now, unlike messages and claims, they don't show their age, so it's
impossible for the user to know when the particular subscription will
expire.

This patch adds 'age' field to subscription resource representation
returned from mongodb driver. Tests are modified to make them check also
'age' field.

Partial-Bug: 1552845
APIImpact
DocImpact
Change-Id: I5eb6a6a267161ec7ee6a7cda094dd55960520069
This commit is contained in:
Eva Balycheva 2016-03-04 01:02:47 +03:00
parent d01946c40f
commit 3b32dfb1ec
3 changed files with 41 additions and 24 deletions

View File

@ -77,17 +77,12 @@ class SubscriptionController(base.Subscription):
cursor = cursor.limit(limit).sort('_id')
marker_name = {}
now = timeutils.utcnow_ts()
def normalizer(record):
ret = {
'id': str(record['_id']),
'source': record['s'],
'subscriber': record['u'],
'ttl': record['t'],
'options': record['o'],
}
marker_name['next'] = record['_id']
return ret
return _basic_subscription(record, now)
yield utils.HookedCursor(cursor, normalizer)
yield marker_name and marker_name['next']
@ -100,7 +95,8 @@ class SubscriptionController(base.Subscription):
if not res:
raise errors.SubscriptionDoesNotExist(subscription_id)
return _normalize(res)
now = timeutils.utcnow_ts()
return _basic_subscription(res, now)
@utils.raises_conn_error
def create(self, queue, subscriber, ttl, options, project=None):
@ -161,13 +157,18 @@ class SubscriptionController(base.Subscription):
'p': project}, w=0)
def _normalize(record):
ret = {
'id': str(record['_id']),
def _basic_subscription(record, now):
# NOTE(Eva-i): unused here record's field 'e' (expires) has changed it's
# format from int (timestamp) to datetime since patch
# 1d122b1671792aff0055ed5396111cd441fb8269. Any future change about
# starting using 'e' field should make sure support both of the formats.
oid = record['_id']
age = now - utils.oid_ts(oid)
return {
'id': str(oid),
'source': record['s'],
'subscriber': record['u'],
'ttl': record['t'],
'age': int(age),
'options': record['o']
}
return ret

View File

@ -1000,6 +1000,8 @@ class SubscriptionControllerTest(ControllerBaseTest):
self.addCleanup(self.subscription_controller.delete, self.source,
s_id, self.project)
added_age = 1
time.sleep(added_age)
interaction = self.subscription_controller.list(self.source,
project=self.project)
subscriptions = list(next(interaction))
@ -1008,6 +1010,7 @@ class SubscriptionControllerTest(ControllerBaseTest):
'source' in s and 'subscriber' in s,
subscriptions)))
self.assertEqual(10, len(subscriptions))
self.assertLessEqual(added_age, subscriptions[2]['age'])
interaction = (self.subscription_controller.list(self.source,
project=self.project,
@ -1032,15 +1035,17 @@ class SubscriptionControllerTest(ControllerBaseTest):
self.ttl,
self.options,
project=self.project)
added_age = 2
time.sleep(added_age)
subscription = self.subscription_controller.get(self.queue_name,
s_id,
self.project)
self.assertEqual(self.source,
subscription['source'])
self.assertEqual(self.subscriber,
subscription['subscriber'])
self.assertEqual(self.source, subscription['source'])
self.assertEqual(self.subscriber, subscription['subscriber'])
self.assertEqual(self.ttl, subscription['ttl'])
self.assertEqual(self.options, subscription['options'])
self.assertLessEqual(added_age, subscription['age'])
exist = self.subscription_controller.exists(self.queue_name,
s_id,

View File

@ -14,6 +14,7 @@
# limitations under the License.
import json
import time
import uuid
import mock
@ -83,6 +84,8 @@ class SubscriptionTest(base.V1_1Base):
req = test_utils.create_request(action, body, self.headers)
self.protocol.onMessage(req, False)
added_age = 1
time.sleep(added_age)
[subscriber] = list(
next(
self.boot.storage.subscription_controller.list(
@ -94,6 +97,7 @@ class SubscriptionTest(base.V1_1Base):
self.assertEqual(600, subscriber['ttl'])
self.assertEqual('http://localhost:1234/%s' % self.protocol.proto_id,
subscriber['subscriber'])
self.assertLessEqual(added_age, subscriber['age'])
self.boot.storage.subscription_controller.delete(
'kitkat', subscriber['id'], project=self.project_id)
@ -176,7 +180,7 @@ class SubscriptionTest(base.V1_1Base):
req = test_utils.create_request(action, body, self.headers)
self.protocol.onMessage(req, False)
response = {
expected_response_without_age = {
'body': {'subscriber': '',
'source': 'kitkat',
'options': {},
@ -189,7 +193,11 @@ class SubscriptionTest(base.V1_1Base):
'api': 'v2', 'headers': self.headers}}
self.assertEqual(1, sender.call_count)
self.assertEqual(response, json.loads(sender.call_args[0][0]))
response = json.loads(sender.call_args[0][0])
# Get and remove age from the actual response.
actual_sub_age = response['body'].pop('age')
self.assertLessEqual(0, actual_sub_age)
self.assertEqual(expected_response_without_age, response)
def test_subscription_list(self):
sub = self.boot.storage.subscription_controller.create(
@ -207,7 +215,7 @@ class SubscriptionTest(base.V1_1Base):
req = test_utils.create_request(action, body, self.headers)
self.protocol.onMessage(req, False)
response = {
expected_response_without_age = {
'body': {
'subscriptions': [{
'subscriber': '',
@ -219,9 +227,12 @@ class SubscriptionTest(base.V1_1Base):
'request': {'action': 'subscription_list',
'body': {'queue_name': 'kitkat'},
'api': 'v2', 'headers': self.headers}}
self.assertEqual(1, sender.call_count)
self.assertEqual(response, json.loads(sender.call_args[0][0]))
response = json.loads(sender.call_args[0][0])
# Get and remove age from the actual response.
actual_sub_age = response['body']['subscriptions'][0].pop('age')
self.assertLessEqual(0, actual_sub_age)
self.assertEqual(expected_response_without_age, response)
def test_subscription_sustainable_notifications_format(self):
# NOTE(Eva-i): The websocket subscription's notifications must be