Accept optional token to public room list

This commit is contained in:
Erik Johnston 2016-09-15 09:08:57 +01:00
parent c566f0ee17
commit 4f181f361d
2 changed files with 76 additions and 7 deletions

View File

@ -24,7 +24,11 @@ from synapse.api.errors import SynapseError
from synapse.util.async import concurrently_execute from synapse.util.async import concurrently_execute
from synapse.util.caches.response_cache import ResponseCache from synapse.util.caches.response_cache import ResponseCache
from collections import namedtuple
from unpaddedbase64 import encode_base64, decode_base64
import logging import logging
import msgpack
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -42,20 +46,31 @@ class RoomListHandler(BaseHandler):
) )
self.fetch_all_remote_lists() self.fetch_all_remote_lists()
def get_local_public_room_list(self): def get_local_public_room_list(self, limit=None, next_batch=None):
result = self.response_cache.get(()) result = self.response_cache.get((limit, next_batch))
if not result: if not result:
result = self.response_cache.set((), self._get_public_room_list()) result = self.response_cache.set(
(limit, next_batch),
self._get_public_room_list(limit, next_batch)
)
return result return result
@defer.inlineCallbacks @defer.inlineCallbacks
def _get_public_room_list(self): def _get_public_room_list(self, limit=None, next_batch=None):
if next_batch and next_batch != "END":
next_batch = RoomListNextBatch.from_token(next_batch)
else:
next_batch = None
room_ids = yield self.store.get_public_room_ids() room_ids = yield self.store.get_public_room_ids()
rooms_to_order_value = {} rooms_to_order_value = {}
rooms_to_num_joined = {} rooms_to_num_joined = {}
rooms_to_latest_event_ids = {} rooms_to_latest_event_ids = {}
if next_batch:
current_stream_token = next_batch.sstream_ordering
else:
current_stream_token = yield self.store.get_room_max_stream_ordering() current_stream_token = yield self.store.get_room_max_stream_ordering()
# We want to return rooms in a particular order: the number of joined # We want to return rooms in a particular order: the number of joined
@ -90,6 +105,17 @@ class RoomListHandler(BaseHandler):
sorted_entries = sorted(rooms_to_order_value.items(), key=lambda e: e[1]) sorted_entries = sorted(rooms_to_order_value.items(), key=lambda e: e[1])
sorted_rooms = [room_id for room_id, _ in sorted_entries] sorted_rooms = [room_id for room_id, _ in sorted_entries]
if next_batch:
sorted_rooms = sorted_rooms[next_batch.current_limit:]
new_limit = None
if limit:
if sorted_rooms[limit:]:
new_limit = limit
if next_batch:
new_limit += next_batch.current_limit
sorted_rooms = sorted_rooms[:limit]
results = [] results = []
@defer.inlineCallbacks @defer.inlineCallbacks
@ -174,8 +200,24 @@ class RoomListHandler(BaseHandler):
yield concurrently_execute(handle_room, sorted_rooms, 10) yield concurrently_execute(handle_room, sorted_rooms, 10)
# FIXME (erikj): START is no longer a valid value if new_limit:
defer.returnValue({"start": "START", "end": "END", "chunk": results}) end_token = RoomListNextBatch(
stream_ordering=current_stream_token,
current_limit=new_limit,
).to_token()
else:
end_token = "END"
if next_batch:
start_token = next_batch.to_token()
else:
start_token = "START"
defer.returnValue({
"start": start_token,
"end": end_token,
"chunk": results,
})
@defer.inlineCallbacks @defer.inlineCallbacks
def fetch_all_remote_lists(self): def fetch_all_remote_lists(self):
@ -235,3 +277,29 @@ class RoomListHandler(BaseHandler):
room_ids.add(room["room_id"]) room_ids.add(room["room_id"])
defer.returnValue(public_rooms) defer.returnValue(public_rooms)
class RoomListNextBatch(namedtuple("RoomListNextBatch", (
"stream_ordering", # stream_ordering of the first public room list
"current_limit", # The number of previous rooms returned
))):
KEY_DICT = {
"stream_ordering": "s",
"current_limit": "n",
}
REVERSE_KEY_DICT = {v: k for k, v in KEY_DICT.items()}
@classmethod
def from_token(cls, token):
return RoomListNextBatch(**{
cls.REVERSE_KEY_DICT[key]: val
for key, val in msgpack.loads(decode_base64(token)).items()
})
def to_token(self):
return encode_base64(msgpack.dumps({
self.KEY_DICT[key]: val
for key, val in self._asdict().items()
}))

View File

@ -36,6 +36,7 @@ REQUIREMENTS = {
"blist": ["blist"], "blist": ["blist"],
"pysaml2>=3.0.0,<4.0.0": ["saml2>=3.0.0,<4.0.0"], "pysaml2>=3.0.0,<4.0.0": ["saml2>=3.0.0,<4.0.0"],
"pymacaroons-pynacl": ["pymacaroons"], "pymacaroons-pynacl": ["pymacaroons"],
"msgpack-python>=0.3.0": ["msgpack"],
} }
CONDITIONAL_REQUIREMENTS = { CONDITIONAL_REQUIREMENTS = {
"web_client": { "web_client": {