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

make /context lazyload & filter aware #3567

Merged
merged 20 commits into from
Jul 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/3567.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
make the /context API filter & lazy-load aware as per MSC1227
24 changes: 21 additions & 3 deletions synapse/handlers/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# limitations under the License.

"""Contains functions for performing events on rooms."""
import itertools
import logging
import math
import string
Expand Down Expand Up @@ -401,7 +402,7 @@ def __init__(self, hs):
self.store = hs.get_datastore()

@defer.inlineCallbacks
def get_event_context(self, user, room_id, event_id, limit):
def get_event_context(self, user, room_id, event_id, limit, event_filter):
"""Retrieves events, pagination tokens and state around a given event
in a room.

Expand All @@ -411,6 +412,8 @@ def get_event_context(self, user, room_id, event_id, limit):
event_id (str)
limit (int): The maximum number of events to return in total
(excluding state).
event_filter (Filter|None): the filter to apply to the events returned
(excluding the target event_id)

Returns:
dict, or None if the event isn't found
Expand Down Expand Up @@ -443,7 +446,7 @@ def filter_evts(events):
)

results = yield self.store.get_events_around(
room_id, event_id, before_limit, after_limit
room_id, event_id, before_limit, after_limit, event_filter
)

results["events_before"] = yield filter_evts(results["events_before"])
Expand All @@ -455,8 +458,23 @@ def filter_evts(events):
else:
last_event_id = event_id

types = None
filtered_types = None
if event_filter and event_filter.lazy_load_members():
members = set(ev.sender for ev in itertools.chain(
results["events_before"],
(results["event"],),
results["events_after"],
))
filtered_types = [EventTypes.Member]
types = [(EventTypes.Member, member) for member in members]

# XXX: why do we return the state as of the last event rather than the
# first? Shouldn't we be consistent with /sync?
# https://github.com/matrix-org/matrix-doc/issues/687

state = yield self.store.get_state_for_events(
[last_event_id], None
[last_event_id], types, filtered_types=filtered_types,
)
results["state"] = list(state[last_event_id].values())

Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def search(self, user, content, batch=None):
contexts = {}
for event in allowed_events:
res = yield self.store.get_events_around(
event.room_id, event.event_id, before_limit, after_limit
event.room_id, event.event_id, before_limit, after_limit,
)

logger.info(
Expand Down
9 changes: 9 additions & 0 deletions synapse/rest/client/v1/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,11 +531,20 @@ def on_GET(self, request, room_id, event_id):

limit = parse_integer(request, "limit", default=10)

# picking the API shape for symmetry with /messages
filter_bytes = parse_string(request, "filter")
if filter_bytes:
filter_json = urlparse.unquote(filter_bytes).decode("UTF-8")
event_filter = Filter(json.loads(filter_json))
else:
event_filter = None

results = yield self.room_context_handler.get_event_context(
requester.user,
room_id,
event_id,
limit,
event_filter,
)

if not results:
Expand Down
14 changes: 11 additions & 3 deletions synapse/storage/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,9 @@ def _set_before_and_after(events, rows, topo_order=True):
)

@defer.inlineCallbacks
def get_events_around(self, room_id, event_id, before_limit, after_limit):
def get_events_around(
self, room_id, event_id, before_limit, after_limit, event_filter=None,
):
"""Retrieve events and pagination tokens around a given event in a
room.

Expand All @@ -536,14 +538,15 @@ def get_events_around(self, room_id, event_id, before_limit, after_limit):
event_id (str)
before_limit (int)
after_limit (int)
event_filter (Filter|None)

Returns:
dict
"""

results = yield self.runInteraction(
"get_events_around", self._get_events_around_txn,
room_id, event_id, before_limit, after_limit
room_id, event_id, before_limit, after_limit, event_filter,
)

events_before = yield self._get_events(
Expand All @@ -563,7 +566,9 @@ def get_events_around(self, room_id, event_id, before_limit, after_limit):
"end": results["after"]["token"],
})

def _get_events_around_txn(self, txn, room_id, event_id, before_limit, after_limit):
def _get_events_around_txn(
self, txn, room_id, event_id, before_limit, after_limit, event_filter,
):
"""Retrieves event_ids and pagination tokens around a given event in a
room.

Expand All @@ -572,6 +577,7 @@ def _get_events_around_txn(self, txn, room_id, event_id, before_limit, after_lim
event_id (str)
before_limit (int)
after_limit (int)
event_filter (Filter|None)

Returns:
dict
Expand Down Expand Up @@ -601,11 +607,13 @@ def _get_events_around_txn(self, txn, room_id, event_id, before_limit, after_lim

rows, start_token = self._paginate_room_events_txn(
txn, room_id, before_token, direction='b', limit=before_limit,
event_filter=event_filter,
)
events_before = [r.event_id for r in rows]

rows, end_token = self._paginate_room_events_txn(
txn, room_id, after_token, direction='f', limit=after_limit,
event_filter=event_filter,
)
events_after = [r.event_id for r in rows]

Expand Down