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

Optimize private read receipt filtering #12711

Merged
1 change: 1 addition & 0 deletions changelog.d/12711.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Optimize private read receipt filtering.
43 changes: 16 additions & 27 deletions synapse/handlers/receipts.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,43 +165,32 @@ def __init__(self, hs: "HomeServer"):
self.config = hs.config

@staticmethod
def filter_out_private(events: List[JsonDict], user_id: str) -> List[JsonDict]:
def filter_out_private(events: List[JsonDict], our_user_id: str) -> List[JsonDict]:
"""
This method takes in what is returned by
get_linearized_receipts_for_rooms() and goes through read receipts
filtering out m.read.private receipts if they were not sent by the
current user.
"""

visible_events = []

events = events.copy()
clokep marked this conversation as resolved.
Show resolved Hide resolved
# filter out private receipts the user shouldn't see
for event in events:
for index, event in enumerate(events):
content = event.get("content", {})
new_event = event.copy()
SimonBrandner marked this conversation as resolved.
Show resolved Hide resolved
new_event["content"] = {}

for event_id, event_content in content.items():
receipt_event = {}
for receipt_type, receipt_content in event_content.items():
for event_id, event_content in list(content.items()):
for receipt_type, receipt_content in list(event_content.items()):
if receipt_type == ReceiptTypes.READ_PRIVATE:
user_rr = receipt_content.get(user_id, None)
if user_rr:
receipt_event[ReceiptTypes.READ_PRIVATE] = {
user_id: user_rr.copy()
}
else:
receipt_event[receipt_type] = receipt_content.copy()

# Only include the receipt event if it is non-empty.
if receipt_event:
new_event["content"][event_id] = receipt_event

# Append new_event to visible_events unless empty
if len(new_event["content"].keys()) > 0:
visible_events.append(new_event)

return visible_events
for user_id in list(receipt_content.keys()):
clokep marked this conversation as resolved.
Show resolved Hide resolved
if user_id != our_user_id:
del receipt_content[user_id]

if len(receipt_content) == 0:
del event_content[receipt_type]
if len(event_content) == 0:
del content[event_id]
if len(content) == 0:
del events[index]
clokep marked this conversation as resolved.
Show resolved Hide resolved
return events

async def get_new_events(
self,
Expand Down
22 changes: 21 additions & 1 deletion tests/handlers/test_receipts.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ def test_handles_missing_content_of_m_read(self):
[
{
"content": {
"$14356419ggffg114394fHBLK:matrix.org": {ReceiptTypes.READ: {}},
"$1435641916114394fHBLK:matrix.org": {
ReceiptTypes.READ: {
"@user:jki.re": {
Expand Down Expand Up @@ -332,6 +331,27 @@ def test_leaves_our_private_and_their_public(self):
],
)

def test_we_do_not_mutate(self):
events = [
{
"content": {
"$1435641916114394fHBLK:matrix.org": {
ReceiptTypes.READ_PRIVATE: {
"@rikj:jki.re": {
"ts": 1436451550453,
}
}
}
},
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
"type": "m.receipt",
}
]
events_copy = events.copy()
SimonBrandner marked this conversation as resolved.
Show resolved Hide resolved

self.event_source.filter_out_private(events, "@me:server.org")
self.assertEqual(events, events_copy)

def _test_filters_private(
self, events: List[JsonDict], expected_output: List[JsonDict]
):
Expand Down