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

Commit f4a6f87

Browse files
committed
Rewrite get HTTP push actions queries
This moves the checking of push action against read receipt into the pusher rather than the database, removing the need for two similar nested queries yielding an overall reduction in database cost.
1 parent 37f329c commit f4a6f87

File tree

1 file changed

+26
-64
lines changed

1 file changed

+26
-64
lines changed

synapse/storage/databases/main/event_push_actions.py

+26-64
Original file line numberDiff line numberDiff line change
@@ -482,14 +482,7 @@ async def get_unread_push_actions_for_user_in_range_for_http(
482482
The list will have between 0~limit entries.
483483
"""
484484

485-
# find rooms that have a read receipt in them and return the next
486-
# push actions
487-
def get_after_receipt(
488-
txn: LoggingTransaction,
489-
) -> List[Tuple[str, str, int, str, bool]]:
490-
# find rooms that have a read receipt in them and return the next
491-
# push actions
492-
485+
def get_receipts_by_room(txn: LoggingTransaction) -> List[Tuple[str, int]]:
493486
receipt_types_clause, args = make_in_list_sql_clause(
494487
self.database_engine,
495488
"receipt_type",
@@ -501,77 +494,43 @@ def get_after_receipt(
501494
)
502495

503496
sql = f"""
504-
SELECT ep.event_id, ep.room_id, ep.stream_ordering, ep.actions,
505-
ep.highlight
506-
FROM (
507-
SELECT room_id,
508-
MAX(stream_ordering) as stream_ordering
509-
FROM events
510-
INNER JOIN receipts_linearized USING (room_id, event_id)
511-
WHERE {receipt_types_clause} AND user_id = ?
512-
GROUP BY room_id
513-
) AS rl,
514-
event_push_actions AS ep
515-
WHERE
516-
ep.room_id = rl.room_id
517-
AND ep.stream_ordering > rl.stream_ordering
518-
AND ep.user_id = ?
519-
AND ep.stream_ordering > ?
520-
AND ep.stream_ordering <= ?
521-
AND ep.notif = 1
522-
ORDER BY ep.stream_ordering ASC LIMIT ?
497+
SELECT room_id, MAX(stream_ordering)
498+
FROM receipts_linearized
499+
INNER JOIN events USING (room_id, event_id)
500+
WHERE {receipt_types_clause}
501+
AND user_id = ?
502+
GROUP BY room_id
523503
"""
524-
args.extend(
525-
(user_id, user_id, min_stream_ordering, max_stream_ordering, limit)
526-
)
504+
505+
args.extend((user_id,))
527506
txn.execute(sql, args)
528-
return cast(List[Tuple[str, str, int, str, bool]], txn.fetchall())
507+
return cast(List[Tuple[str, int]], txn.fetchall())
529508

530-
after_read_receipt = await self.db_pool.runInteraction(
531-
"get_unread_push_actions_for_user_in_range_http_arr", get_after_receipt
509+
receipts_by_room = dict(
510+
await self.db_pool.runInteraction(
511+
"get_unread_push_actions_for_user_in_range_http_receipts",
512+
get_receipts_by_room,
513+
),
532514
)
533515

534-
# There are rooms with push actions in them but you don't have a read receipt in
535-
# them e.g. rooms you've been invited to, so get push actions for rooms which do
536-
# not have read receipts in them too.
537-
def get_no_receipt(
516+
def get_push_actions(
538517
txn: LoggingTransaction,
539518
) -> List[Tuple[str, str, int, str, bool]]:
540-
receipt_types_clause, args = make_in_list_sql_clause(
541-
self.database_engine,
542-
"receipt_type",
543-
(
544-
ReceiptTypes.READ,
545-
ReceiptTypes.READ_PRIVATE,
546-
ReceiptTypes.UNSTABLE_READ_PRIVATE,
547-
),
548-
)
549-
550-
sql = f"""
551-
SELECT ep.event_id, ep.room_id, ep.stream_ordering, ep.actions,
552-
ep.highlight
519+
sql = """
520+
SELECT ep.event_id, ep.room_id, ep.stream_ordering, ep.actions, ep.highlight
553521
FROM event_push_actions AS ep
554-
INNER JOIN events AS e USING (room_id, event_id)
555522
WHERE
556-
ep.room_id NOT IN (
557-
SELECT room_id FROM receipts_linearized
558-
WHERE {receipt_types_clause} AND user_id = ?
559-
GROUP BY room_id
560-
)
561-
AND ep.user_id = ?
523+
ep.user_id = ?
562524
AND ep.stream_ordering > ?
563525
AND ep.stream_ordering <= ?
564526
AND ep.notif = 1
565527
ORDER BY ep.stream_ordering ASC LIMIT ?
566528
"""
567-
args.extend(
568-
(user_id, user_id, min_stream_ordering, max_stream_ordering, limit)
569-
)
570-
txn.execute(sql, args)
529+
txn.execute(sql, (user_id, min_stream_ordering, max_stream_ordering, limit))
571530
return cast(List[Tuple[str, str, int, str, bool]], txn.fetchall())
572531

573-
no_read_receipt = await self.db_pool.runInteraction(
574-
"get_unread_push_actions_for_user_in_range_http_nrr", get_no_receipt
532+
push_actions = await self.db_pool.runInteraction(
533+
"get_unread_push_actions_for_user_in_range_http", get_push_actions
575534
)
576535

577536
notifs = [
@@ -581,7 +540,10 @@ def get_no_receipt(
581540
stream_ordering=row[2],
582541
actions=_deserialize_action(row[3], row[4]),
583542
)
584-
for row in after_read_receipt + no_read_receipt
543+
for row in push_actions
544+
# Only include push actions with a stream ordering after any receipt, or without any
545+
# receipt present (invited to but never read rooms).
546+
if row[2] > receipts_by_room.get(row[1], 0)
585547
]
586548

587549
# Now sort it so it's ordered correctly, since currently it will

0 commit comments

Comments
 (0)