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

Commit b44fbdf

Browse files
authored
Move free functions into PushRuleEvaluatorForEvent. (#12677)
* Move `_condition_checker` into `PushRuleEvaluatorForEvent`. * Move the condition cache into `PushRuleEvaluatorForEvent`. * Improve docstrings. * Inline a method which is only called once.
1 parent 02cdace commit b44fbdf

File tree

3 files changed

+69
-34
lines changed

3 files changed

+69
-34
lines changed

changelog.d/12677.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Refactor functions to on `PushRuleEvaluatorForEvent`.

synapse/push/bulk_push_rule_evaluator.py

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,6 @@ async def action_for_event_by_user(
208208
event, len(room_members), sender_power_level, power_levels
209209
)
210210

211-
condition_cache: Dict[str, bool] = {}
212-
213211
# If the event is not a state event check if any users ignore the sender.
214212
if not event.is_state():
215213
ignorers = await self.store.ignored_by(event.sender)
@@ -247,8 +245,8 @@ async def action_for_event_by_user(
247245
if "enabled" in rule and not rule["enabled"]:
248246
continue
249247

250-
matches = _condition_checker(
251-
evaluator, rule["conditions"], uid, display_name, condition_cache
248+
matches = evaluator.check_conditions(
249+
rule["conditions"], uid, display_name
252250
)
253251
if matches:
254252
actions = [x for x in rule["actions"] if x != "dont_notify"]
@@ -267,32 +265,6 @@ async def action_for_event_by_user(
267265
)
268266

269267

270-
def _condition_checker(
271-
evaluator: PushRuleEvaluatorForEvent,
272-
conditions: List[dict],
273-
uid: str,
274-
display_name: Optional[str],
275-
cache: Dict[str, bool],
276-
) -> bool:
277-
for cond in conditions:
278-
_cache_key = cond.get("_cache_key", None)
279-
if _cache_key:
280-
res = cache.get(_cache_key, None)
281-
if res is False:
282-
return False
283-
elif res is True:
284-
continue
285-
286-
res = evaluator.matches(cond, uid, display_name)
287-
if _cache_key:
288-
cache[_cache_key] = bool(res)
289-
290-
if not res:
291-
return False
292-
293-
return True
294-
295-
296268
MemberMap = Dict[str, Optional[EventIdMembership]]
297269
Rule = Dict[str, dict]
298270
RulesByUser = Dict[str, List[Rule]]

synapse/push/push_rule_evaluator.py

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,55 @@ def __init__(
129129
# Maps strings of e.g. 'content.body' -> event["content"]["body"]
130130
self._value_cache = _flatten_dict(event)
131131

132+
# Maps cache keys to final values.
133+
self._condition_cache: Dict[str, bool] = {}
134+
135+
def check_conditions(
136+
self, conditions: List[dict], uid: str, display_name: Optional[str]
137+
) -> bool:
138+
"""
139+
Returns true if a user's conditions/user ID/display name match the event.
140+
141+
Args:
142+
conditions: The user's conditions to match.
143+
uid: The user's MXID.
144+
display_name: The display name.
145+
146+
Returns:
147+
True if all conditions match the event, False otherwise.
148+
"""
149+
for cond in conditions:
150+
_cache_key = cond.get("_cache_key", None)
151+
if _cache_key:
152+
res = self._condition_cache.get(_cache_key, None)
153+
if res is False:
154+
return False
155+
elif res is True:
156+
continue
157+
158+
res = self.matches(cond, uid, display_name)
159+
if _cache_key:
160+
self._condition_cache[_cache_key] = bool(res)
161+
162+
if not res:
163+
return False
164+
165+
return True
166+
132167
def matches(
133168
self, condition: Dict[str, Any], user_id: str, display_name: Optional[str]
134169
) -> bool:
170+
"""
171+
Returns true if a user's condition/user ID/display name match the event.
172+
173+
Args:
174+
condition: The user's condition to match.
175+
uid: The user's MXID.
176+
display_name: The display name, or None if there is not one.
177+
178+
Returns:
179+
True if the condition matches the event, False otherwise.
180+
"""
135181
if condition["kind"] == "event_match":
136182
return self._event_match(condition, user_id)
137183
elif condition["kind"] == "contains_display_name":
@@ -146,6 +192,16 @@ def matches(
146192
return True
147193

148194
def _event_match(self, condition: dict, user_id: str) -> bool:
195+
"""
196+
Check an "event_match" push rule condition.
197+
198+
Args:
199+
condition: The "event_match" push rule condition to match.
200+
user_id: The user's MXID.
201+
202+
Returns:
203+
True if the condition matches the event, False otherwise.
204+
"""
149205
pattern = condition.get("pattern", None)
150206

151207
if not pattern:
@@ -167,13 +223,22 @@ def _event_match(self, condition: dict, user_id: str) -> bool:
167223

168224
return _glob_matches(pattern, body, word_boundary=True)
169225
else:
170-
haystack = self._get_value(condition["key"])
226+
haystack = self._value_cache.get(condition["key"], None)
171227
if haystack is None:
172228
return False
173229

174230
return _glob_matches(pattern, haystack)
175231

176232
def _contains_display_name(self, display_name: Optional[str]) -> bool:
233+
"""
234+
Check an "event_match" push rule condition.
235+
236+
Args:
237+
display_name: The display name, or None if there is not one.
238+
239+
Returns:
240+
True if the display name is found in the event body, False otherwise.
241+
"""
177242
if not display_name:
178243
return False
179244

@@ -191,9 +256,6 @@ def _contains_display_name(self, display_name: Optional[str]) -> bool:
191256

192257
return bool(r.search(body))
193258

194-
def _get_value(self, dotted_key: str) -> Optional[str]:
195-
return self._value_cache.get(dotted_key, None)
196-
197259

198260
# Caches (string, is_glob, word_boundary) -> regex for push. See _glob_matches
199261
regex_cache: LruCache[Tuple[str, bool, bool], Pattern] = LruCache(

0 commit comments

Comments
 (0)