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

Commit c0ecdf2

Browse files
committed
Rework to pull less information from the database.
1 parent 8851217 commit c0ecdf2

File tree

5 files changed

+67
-30
lines changed

5 files changed

+67
-30
lines changed

synapse/push/bulk_push_rule_evaluator.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16+
import itertools
1617
import logging
1718
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, Union
1819

@@ -215,16 +216,33 @@ async def action_for_event_by_user(
215216
) = await self._get_power_levels_and_sender_level(event, context)
216217

217218
# If the experimental feature is not enabled, skip fetching relations.
218-
if self._relations_match_enabled:
219+
relations = {}
220+
if self._relations_match_enabled or True:
221+
# If the event does not have a relation, then cannot have any mutual
222+
# relations.
219223
relation = relation_from_event(event)
220224
if relation:
221-
relations = await self.store.get_mutual_event_relations(
222-
relation.parent_id
223-
)
224-
else:
225-
relations = set()
226-
else:
227-
relations = set()
225+
# Pre-filter to figure out which relation types are interesting.
226+
rel_types = set()
227+
for rule in itertools.chain(*rules_by_user.values()):
228+
# Skip disabled rules.
229+
if not rule.get("enabled"):
230+
continue
231+
232+
for condition in rule["conditions"]:
233+
if condition["kind"] != "org.matrix.msc3772.relation_match":
234+
continue
235+
236+
# rel_type is required.
237+
rel_type = condition.get("rel_type")
238+
if rel_type:
239+
rel_types.add(rel_type)
240+
241+
# If any valid rules were found, fetch the mutual relations.
242+
if rel_types:
243+
relations = await self.store.get_mutual_event_relations(
244+
relation.parent_id, rel_types
245+
)
228246

229247
evaluator = PushRuleEvaluatorForEvent(
230248
event,

synapse/push/push_rule_evaluator.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def __init__(
120120
room_member_count: int,
121121
sender_power_level: int,
122122
power_levels: Dict[str, Union[int, Dict[str, int]]],
123-
relations: Set[Tuple[str, str, str]],
123+
relations: Dict[str, Set[Tuple[str, str]]],
124124
relations_match_enabled: bool,
125125
):
126126
self._event = event
@@ -293,12 +293,10 @@ def _relation_match(self, condition: dict, user_id: str) -> bool:
293293
type_pattern = condition.get("type")
294294

295295
# If any other relations matches, return True.
296-
for relation in self._relations:
297-
if rel_type != relation[0]:
296+
for sender, event_type in self._relations.get(rel_type, ()):
297+
if sender_pattern and not _glob_matches(sender_pattern, sender):
298298
continue
299-
if sender_pattern and not _glob_matches(sender_pattern, relation[1]):
300-
continue
301-
if type_pattern and not _glob_matches(type_pattern, relation[2]):
299+
if type_pattern and not _glob_matches(type_pattern, event_type):
302300
continue
303301
# All values must have matched.
304302
return True

synapse/storage/databases/main/events.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,7 +1829,7 @@ def _handle_event_relations(
18291829
(relation.parent_id,),
18301830
)
18311831
txn.call_after(
1832-
self.store.get_mutual_event_relations.invalidate,
1832+
self.store.get_mutual_event_relations_for_rel_type.invalidate,
18331833
(relation.parent_id,),
18341834
)
18351835

@@ -2009,7 +2009,9 @@ def _handle_redact_relations(
20092009
txn, self.store.get_thread_participated, (redacted_relates_to,)
20102010
)
20112011
self.store._invalidate_cache_and_stream(
2012-
txn, self.store.get_mutual_event_relations, (redacted_relates_to,)
2012+
txn,
2013+
self.store.get_mutual_event_relations_for_rel_type,
2014+
(redacted_relates_to,),
20132015
)
20142016

20152017
self.db_pool.simple_delete_txn(

synapse/storage/databases/main/relations.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import logging
16+
from collections import defaultdict
1617
from typing import (
1718
Collection,
1819
Dict,
@@ -768,9 +769,18 @@ def _get_if_user_has_annotated_event(txn: LoggingTransaction) -> bool:
768769
)
769770

770771
@cached(iterable=True)
772+
async def get_mutual_event_relations_for_rel_type(
773+
self, event_id: str, relation_type: str
774+
) -> Set[Tuple[str, str]]:
775+
raise NotImplementedError()
776+
777+
@cachedList(
778+
cached_method_name="get_mutual_event_relations_for_rel_type",
779+
list_name="relation_types",
780+
)
771781
async def get_mutual_event_relations(
772-
self, event_id: str
773-
) -> Set[Tuple[str, str, str]]:
782+
self, event_id: str, relation_types: Collection[str]
783+
) -> Dict[str, Set[Tuple[str, str]]]:
774784
"""
775785
Fetch event metadata for events which related to the same event as the given event.
776786
@@ -780,20 +790,29 @@ async def get_mutual_event_relations(
780790
event_id: The event ID which is targeted by relations.
781791
782792
Returns:
783-
A set of tuples of:
784-
The relation type
785-
The sender
786-
The event type
793+
A dictionary of relation type to:
794+
A set of tuples of:
795+
The sender
796+
The event type
787797
"""
788-
sql = """
798+
rel_type_sql, rel_type_args = make_in_list_sql_clause(
799+
self.database_engine, "rel_type", relation_types
800+
)
801+
802+
sql = f"""
789803
SELECT DISTINCT relation_type, sender, type FROM event_relations
790804
INNER JOIN events USING (event_id)
791-
WHERE relates_to_id = ?
805+
WHERE relates_to_id = ? AND {rel_type_sql}
792806
"""
793807

794-
def _get_event_relations(txn: LoggingTransaction) -> Set[Tuple[str, str, str]]:
795-
txn.execute(sql, (event_id,))
796-
return set(cast(List[Tuple[str, str, str]], txn.fetchall()))
808+
def _get_event_relations(
809+
txn: LoggingTransaction,
810+
) -> Dict[str, Set[Tuple[str, str]]]:
811+
txn.execute(sql, [event_id] + rel_type_args)
812+
result = defaultdict(set)
813+
for rel_type, sender, type in txn.fetchall():
814+
result[rel_type].add((sender, type))
815+
return result
797816

798817
return await self.db_pool.runInteraction(
799818
"get_event_relations", _get_event_relations

tests/push/test_push_rule_evaluator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
2929
def _get_evaluator(
3030
self,
3131
content: JsonDict,
32-
relations: Optional[Set[Tuple[str, str, str]]] = None,
32+
relations: Optional[Dict[str, Set[Tuple[str, str]]]] = None,
3333
relations_match_enabled: bool = False,
3434
) -> PushRuleEvaluatorForEvent:
3535
event = FrozenEvent(
@@ -292,15 +292,15 @@ def test_relation_match(self) -> None:
292292

293293
# Check if the experimental feature is disabled.
294294
evaluator = self._get_evaluator(
295-
{}, {("m.annotation", "@user:test", "m.reaction")}
295+
{}, {"m.annotation": {("@user:test", "m.reaction")}}
296296
)
297297
condition = {"kind": "relation_match"}
298298
# Oddly, an unknown condition always matches.
299299
self.assertTrue(evaluator.matches(condition, "@user:test", "foo"))
300300

301301
# A push rule evaluator with the experimental rule enabled.
302302
evaluator = self._get_evaluator(
303-
{}, {("m.annotation", "@user:test", "m.reaction")}, True
303+
{}, {"m.annotation": {("@user:test", "m.reaction")}}, True
304304
)
305305

306306
# Check just relation type.

0 commit comments

Comments
 (0)