Flavio Percoco ddd41adab1 Don't stream by default
Current `_Iterator` streams data from the server by default. This
behavior, although useful, shouldn't be considered a sane default. A
good example is when using `limit` on listing operations. If the default
is to stream, the limit will be ignored because the server client will
get everything from the server until there's anything left to consume.
This behavior can also be harmful if not used carefully.

This patch adds a `stream` method to the iterator and makes using this
behavior an explicit operation. The user has to opt-in for data
streaming.

Change-Id: Ib1af24960dff97cb956990d4caf88705f2f7a0d5
2014-04-22 13:20:58 +02:00

112 lines
4.2 KiB
Python

# Copyright (c) 2013 Rackspace, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import mock
from marconiclient.queues.v1 import iterator as iterate
from marconiclient.queues.v1 import message
from marconiclient.tests.queues import base
from marconiclient.tests.queues import messages as test_message
from marconiclient.transport import http
from marconiclient.transport import response
class TestMessageIterator(base.QueuesTestBase):
def test_no_next_iteration(self):
messages = {'links': [],
'messages': [{
'href': '/v1/queues/mine/messages/123123423',
'ttl': 800,
'age': 790,
'body': {'event': 'ActivateAccount',
'mode': 'active'}
}]
}
iterator = iterate._Iterator(self.queue.client,
messages,
'messages',
message.create_object(self.queue))
iterated = [msg for msg in iterator]
self.assertEqual(len(iterated), 1)
def test_stream(self):
messages = {'links': [],
'messages': [{
'href': '/v1/queues/mine/messages/123123423',
'ttl': 800,
'age': 790,
'body': {'event': 'ActivateAccount',
'mode': 'active'}
}]
}
with mock.patch.object(self.transport, 'send',
autospec=True) as send_method:
resp = response.Response(None, json.dumps(messages))
send_method.return_value = resp
# NOTE(flaper87): The first iteration will return 1 message
# and then call `_next_page` which will use the rel-next link
# to get a new set of messages.
link = {'rel': 'next',
'href': "/v1/queues/mine/messages?marker=6244-244224-783"}
messages['links'].append(link)
iterator = iterate._Iterator(self.queue.client,
messages,
'messages',
message.create_object(self.queue))
iterated = [msg for msg in iterator.stream()]
self.assertEqual(len(iterated), 2)
def test_iterator_respect_paging(self):
messages = {'links': [],
'messages': [{
'href': '/v1/queues/mine/messages/123123423',
'ttl': 800,
'age': 790,
'body': {'event': 'ActivateAccount',
'mode': 'active'}
}]
}
with mock.patch.object(self.transport, 'send',
autospec=True) as send_method:
resp = response.Response(None, json.dumps(messages))
send_method.return_value = resp
link = {'rel': 'next',
'href': "/v1/queues/mine/messages?marker=6244-244224-783"}
messages['links'].append(link)
iterator = iterate._Iterator(self.queue.client,
messages,
'messages',
message.create_object(self.queue))
iterated = [msg for msg in iterator]
self.assertEqual(len(iterated), 1)
class QueuesV1MessageHttpUnitTest(test_message.QueuesV1MessageUnitTest):
transport_cls = http.HttpTransport
url = 'http://127.0.0.1:8888/v1'
version = 1