Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit b1b6dba

Browse files
Merge pull request #4415 from matrix-org/anoa/full_search_upgraded_rooms
Ability to search entire room history after upgrading room
2 parents 28c21cd + a383289 commit b1b6dba

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

changelog.d/4415.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Search now includes results from predecessor rooms after a room upgrade.

synapse/api/filtering.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,20 @@ def lazy_load_members(self):
444444
def include_redundant_members(self):
445445
return self.filter_json.get("include_redundant_members", False)
446446

447+
def with_room_ids(self, room_ids):
448+
"""Returns a new filter with the given room IDs appended.
449+
450+
Args:
451+
room_ids (iterable[unicode]): The room_ids to add
452+
453+
Returns:
454+
filter: A new filter including the given rooms and the old
455+
filter's rooms.
456+
"""
457+
newFilter = Filter(self.filter_json)
458+
newFilter.rooms += room_ids
459+
return newFilter
460+
447461

448462
def _matches_wildcard(actual_value, filter_value):
449463
if filter_value.endswith("*"):

synapse/handlers/search.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,41 @@ class SearchHandler(BaseHandler):
3737
def __init__(self, hs):
3838
super(SearchHandler, self).__init__(hs)
3939

40+
@defer.inlineCallbacks
41+
def get_old_rooms_from_upgraded_room(self, room_id):
42+
"""Retrieves room IDs of old rooms in the history of an upgraded room.
43+
44+
We do so by checking the m.room.create event of the room for a
45+
`predecessor` key. If it exists, we add the room ID to our return
46+
list and then check that room for a m.room.create event and so on
47+
until we can no longer find any more previous rooms.
48+
49+
The full list of all found rooms in then returned.
50+
51+
Args:
52+
room_id (str): id of the room to search through.
53+
54+
Returns:
55+
Deferred[iterable[unicode]]: predecessor room ids
56+
"""
57+
58+
historical_room_ids = []
59+
60+
while True:
61+
predecessor = yield self.store.get_room_predecessor(room_id)
62+
63+
# If no predecessor, assume we've hit a dead end
64+
if not predecessor:
65+
break
66+
67+
# Add predecessor's room ID
68+
historical_room_ids.append(predecessor["room_id"])
69+
70+
# Scan through the old room for further predecessors
71+
room_id = predecessor["room_id"]
72+
73+
defer.returnValue(historical_room_ids)
74+
4075
@defer.inlineCallbacks
4176
def search(self, user, content, batch=None):
4277
"""Performs a full text search for a user.
@@ -137,6 +172,18 @@ def search(self, user, content, batch=None):
137172
)
138173
room_ids = set(r.room_id for r in rooms)
139174

175+
# If doing a subset of all rooms seearch, check if any of the rooms
176+
# are from an upgraded room, and search their contents as well
177+
if search_filter.rooms:
178+
historical_room_ids = []
179+
for room_id in search_filter.rooms:
180+
# Add any previous rooms to the search if they exist
181+
ids = yield self.get_old_rooms_from_upgraded_room(room_id)
182+
historical_room_ids += ids
183+
184+
# Prevent any historical events from being filtered
185+
search_filter = search_filter.with_room_ids(historical_room_ids)
186+
140187
room_ids = search_filter.filter_rooms(room_ids)
141188

142189
if batch_group == "room_id":

synapse/storage/state.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,30 @@ def get_room_version(self, room_id):
437437
create_event = yield self.get_event(create_id)
438438
defer.returnValue(create_event.content.get("room_version", "1"))
439439

440+
@defer.inlineCallbacks
441+
def get_room_predecessor(self, room_id):
442+
"""Get the predecessor room of an upgraded room if one exists.
443+
Otherwise return None.
444+
445+
Args:
446+
room_id (str)
447+
448+
Returns:
449+
Deferred[unicode|None]: predecessor room id
450+
"""
451+
state_ids = yield self.get_current_state_ids(room_id)
452+
create_id = state_ids.get((EventTypes.Create, ""))
453+
454+
# If we can't find the create event, assume we've hit a dead end
455+
if not create_id:
456+
defer.returnValue(None)
457+
458+
# Retrieve the room's create event
459+
create_event = yield self.get_event(create_id)
460+
461+
# Return predecessor if present
462+
defer.returnValue(create_event.content.get("predecessor", None))
463+
440464
@cached(max_entries=100000, iterable=True)
441465
def get_current_state_ids(self, room_id):
442466
"""Get the current state event ids for a room based on the

0 commit comments

Comments
 (0)