Allow paginating both forwards and backwards
parent
4131381123
commit
f3eead0660
|
@ -63,7 +63,7 @@ class RoomListHandler(BaseHandler):
|
||||||
rooms_to_latest_event_ids = {}
|
rooms_to_latest_event_ids = {}
|
||||||
|
|
||||||
if next_batch:
|
if next_batch:
|
||||||
current_stream_token = next_batch.sstream_ordering
|
current_stream_token = next_batch.stream_ordering
|
||||||
else:
|
else:
|
||||||
current_stream_token = yield self.store.get_room_max_stream_ordering()
|
current_stream_token = yield self.store.get_room_max_stream_ordering()
|
||||||
|
|
||||||
|
@ -100,17 +100,25 @@ class RoomListHandler(BaseHandler):
|
||||||
sorted_rooms = [room_id for room_id, _ in sorted_entries]
|
sorted_rooms = [room_id for room_id, _ in sorted_entries]
|
||||||
|
|
||||||
if next_batch:
|
if next_batch:
|
||||||
|
if next_batch.direction_is_forward:
|
||||||
sorted_rooms = sorted_rooms[next_batch.current_limit:]
|
sorted_rooms = sorted_rooms[next_batch.current_limit:]
|
||||||
|
else:
|
||||||
|
sorted_rooms = sorted_rooms[:next_batch.current_limit]
|
||||||
|
sorted_rooms.reverse()
|
||||||
|
|
||||||
new_limit = None
|
new_limit = None
|
||||||
if limit:
|
if limit:
|
||||||
if sorted_rooms[limit:]:
|
if sorted_rooms[limit:]:
|
||||||
new_limit = limit
|
new_limit = limit
|
||||||
if next_batch:
|
if next_batch:
|
||||||
|
if next_batch.direction_is_forward:
|
||||||
new_limit += next_batch.current_limit
|
new_limit += next_batch.current_limit
|
||||||
|
else:
|
||||||
|
new_limit = next_batch.current_limit - new_limit
|
||||||
|
new_limit = max(0, new_limit)
|
||||||
sorted_rooms = sorted_rooms[:limit]
|
sorted_rooms = sorted_rooms[:limit]
|
||||||
|
|
||||||
results = []
|
chunk = []
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def handle_room(room_id):
|
def handle_room(room_id):
|
||||||
|
@ -190,31 +198,45 @@ class RoomListHandler(BaseHandler):
|
||||||
if avatar_url:
|
if avatar_url:
|
||||||
result["avatar_url"] = avatar_url
|
result["avatar_url"] = avatar_url
|
||||||
|
|
||||||
results.append(result)
|
chunk.append(result)
|
||||||
|
|
||||||
yield concurrently_execute(handle_room, sorted_rooms, 10)
|
yield concurrently_execute(handle_room, sorted_rooms, 10)
|
||||||
|
|
||||||
|
chunk.sort(key=lambda e: (-e["num_joined_members"], e["room_id"]))
|
||||||
|
|
||||||
|
results = {
|
||||||
|
"chunk": chunk,
|
||||||
|
}
|
||||||
|
|
||||||
|
if not next_batch or next_batch.direction_is_forward:
|
||||||
if new_limit:
|
if new_limit:
|
||||||
end_token = RoomListNextBatch(
|
results["next_batch"] = RoomListNextBatch(
|
||||||
stream_ordering=current_stream_token,
|
stream_ordering=current_stream_token,
|
||||||
current_limit=new_limit,
|
current_limit=new_limit,
|
||||||
|
direction_is_forward=True,
|
||||||
).to_token()
|
).to_token()
|
||||||
else:
|
|
||||||
end_token = "END"
|
|
||||||
|
|
||||||
if next_batch:
|
if next_batch:
|
||||||
start_token = next_batch.to_token()
|
results["prev_batch"] = next_batch.copy_and_replace(
|
||||||
|
direction_is_forward=False,
|
||||||
|
).to_token()
|
||||||
else:
|
else:
|
||||||
start_token = "START"
|
if new_limit:
|
||||||
|
results["prev_batch"] = RoomListNextBatch(
|
||||||
|
stream_ordering=current_stream_token,
|
||||||
|
current_limit=new_limit,
|
||||||
|
direction_is_forward=False,
|
||||||
|
).to_token()
|
||||||
|
|
||||||
defer.returnValue({
|
if next_batch:
|
||||||
"start": start_token,
|
results["next_batch"] = next_batch.copy_and_replace(
|
||||||
"end": end_token,
|
direction_is_forward=True,
|
||||||
"chunk": results,
|
).to_token()
|
||||||
})
|
|
||||||
|
defer.returnValue(results)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def get_remote_public_room_list(self, server_name):
|
def get_remote_public_room_list(self, server_name, limit=None, next_batch=None):
|
||||||
res = yield self.hs.get_replication_layer().get_public_rooms(
|
res = yield self.hs.get_replication_layer().get_public_rooms(
|
||||||
[server_name]
|
[server_name]
|
||||||
)
|
)
|
||||||
|
@ -227,11 +249,13 @@ class RoomListHandler(BaseHandler):
|
||||||
class RoomListNextBatch(namedtuple("RoomListNextBatch", (
|
class RoomListNextBatch(namedtuple("RoomListNextBatch", (
|
||||||
"stream_ordering", # stream_ordering of the first public room list
|
"stream_ordering", # stream_ordering of the first public room list
|
||||||
"current_limit", # The number of previous rooms returned
|
"current_limit", # The number of previous rooms returned
|
||||||
|
"direction_is_forward", # Bool if this is a next_batch, false if prev_batch
|
||||||
))):
|
))):
|
||||||
|
|
||||||
KEY_DICT = {
|
KEY_DICT = {
|
||||||
"stream_ordering": "s",
|
"stream_ordering": "s",
|
||||||
"current_limit": "n",
|
"current_limit": "n",
|
||||||
|
"direction_is_forward": "d",
|
||||||
}
|
}
|
||||||
|
|
||||||
REVERSE_KEY_DICT = {v: k for k, v in KEY_DICT.items()}
|
REVERSE_KEY_DICT = {v: k for k, v in KEY_DICT.items()}
|
||||||
|
@ -248,3 +272,8 @@ class RoomListNextBatch(namedtuple("RoomListNextBatch", (
|
||||||
self.KEY_DICT[key]: val
|
self.KEY_DICT[key]: val
|
||||||
for key, val in self._asdict().items()
|
for key, val in self._asdict().items()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
def copy_and_replace(self, **kwds):
|
||||||
|
return self._replace(
|
||||||
|
**kwds
|
||||||
|
)
|
||||||
|
|
|
@ -23,7 +23,9 @@ from synapse.api.constants import EventTypes, Membership
|
||||||
from synapse.api.filtering import Filter
|
from synapse.api.filtering import Filter
|
||||||
from synapse.types import UserID, RoomID, RoomAlias
|
from synapse.types import UserID, RoomID, RoomAlias
|
||||||
from synapse.events.utils import serialize_event, format_event_for_client_v2
|
from synapse.events.utils import serialize_event, format_event_for_client_v2
|
||||||
from synapse.http.servlet import parse_json_object_from_request, parse_string
|
from synapse.http.servlet import (
|
||||||
|
parse_json_object_from_request, parse_string, parse_integer
|
||||||
|
)
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import urllib
|
import urllib
|
||||||
|
@ -317,11 +319,21 @@ class PublicRoomListRestServlet(ClientV1RestServlet):
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
limit = parse_integer(request, "limit", 0)
|
||||||
|
next_batch = parse_string(request, "since", None)
|
||||||
|
|
||||||
handler = self.hs.get_room_list_handler()
|
handler = self.hs.get_room_list_handler()
|
||||||
if server:
|
if server:
|
||||||
data = yield handler.get_remote_public_room_list(server)
|
data = yield handler.get_remote_public_room_list(
|
||||||
|
server,
|
||||||
|
limit=limit,
|
||||||
|
next_batch=next_batch,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
data = yield handler.get_local_public_room_list()
|
data = yield handler.get_local_public_room_list(
|
||||||
|
limit=limit,
|
||||||
|
next_batch=next_batch,
|
||||||
|
)
|
||||||
|
|
||||||
defer.returnValue((200, data))
|
defer.returnValue((200, data))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue