Add mark/limit paging to find call.

Adds Mark/limit to find_streams for api usage.

The 'mark' is an opaque parameter (called '_mark') added into
each item in the list of returned items (currently a mildly obscured
ID for streams, that could be changed.)

Returned items are sorted in descending order (by ID for streams),
allowing paging from the 'top' to the bottom.
By prefacing the 'mark' param with a '+', you can page in ascending
order as well.

This same paging scheme can be used for a future events api, as well.

Change-Id: Ie358c0d1d8644dac24cad3992188ec22d66c5328
This commit is contained in:
Monsyne Dragon 2015-02-10 19:29:07 +00:00
parent 6557de033c
commit 8044f3e7e2
2 changed files with 54 additions and 1 deletions

View File

@ -449,3 +449,29 @@ class TestDB(unittest.TestCase):
def test_find_stream_count(self):
count = self.db.find_streams(count=True)
self.assertEqual([{'count': 8}], count)
def test_find_stream_limit(self):
streams = self.db.find_streams(limit=2)
self.assertEqual(len(streams), 2)
self.assertEqual(streams[0]['id'], 8)
self.assertEqual(streams[1]['id'], 7)
def test_find_stream_limit_asc(self):
streams = self.db.find_streams(limit=2, mark='+')
self.assertEqual(len(streams), 2)
self.assertEqual(streams[0]['id'], 1)
self.assertEqual(streams[1]['id'], 2)
def test_find_stream_mark(self):
streams = self.db.find_streams(mark='7')
for stream in streams:
self.assertIn('_mark', stream)
self.assertEqual(streams[0]['id'], 6)
self.assertEqual(streams[1]['id'], 5)
def test_find_stream_mark_asc(self):
streams = self.db.find_streams(mark='+2')
for stream in streams:
self.assertIn('_mark', stream)
self.assertEqual(streams[0]['id'], 3)
self.assertEqual(streams[1]['id'], 4)

View File

@ -238,8 +238,24 @@ class DBInterface(object):
def find_streams(self, count=False, stream_id=None, state=None,
older_than=None, younger_than=None,
name=None, distinguishing_traits=None,
session=None, include_events=False):
session=None, include_events=False,
limit=None, mark=None):
order_desc = True
q = session.query(models.Stream)
if mark is not None:
if mark.startswith('+'):
order_desc=False
mark = mark[1:]
if mark.startswith('-'):
order_desc=True
mark = mark[1:]
if mark:
if order_desc:
q = q.filter(models.Stream.id < int(mark, 16))
else:
q = q.filter(models.Stream.id > int(mark, 16))
if stream_id is not None:
q = q.filter(models.Stream.id == stream_id)
if state is not None:
@ -260,9 +276,20 @@ class DBInterface(object):
q = q.count()
return [{"count": q}]
if order_desc:
q = q.order_by(models.Stream.id.desc())
mark_fmt = '%x'
else:
q = q.order_by(models.Stream.id.asc())
mark_fmt = '+%x'
if limit is not None:
q = q.limit(limit)
stream_info = []
for stream in q.all():
info = stream.as_dict
info['_mark'] = mark_fmt % stream.id
if include_events:
info['events'] = self.get_stream_events(stream, session=session)
stream_info.append(info)