|
13 | 13 | # limitations under the License. |
14 | 14 | import enum |
15 | 15 | import logging |
16 | | -from typing import ( |
17 | | - TYPE_CHECKING, |
18 | | - Collection, |
19 | | - Dict, |
20 | | - FrozenSet, |
21 | | - Iterable, |
22 | | - List, |
23 | | - Optional, |
24 | | - Tuple, |
25 | | -) |
| 16 | +from typing import TYPE_CHECKING, Collection, Dict, FrozenSet, Iterable, List, Optional |
26 | 17 |
|
27 | 18 | import attr |
28 | 19 |
|
|
32 | 23 | from synapse.logging.opentracing import trace |
33 | 24 | from synapse.storage.databases.main.relations import ThreadsNextBatch, _RelatedEvent |
34 | 25 | from synapse.streams.config import PaginationConfig |
35 | | -from synapse.types import JsonDict, Requester, StreamToken, UserID |
| 26 | +from synapse.types import JsonDict, Requester, UserID |
36 | 27 | from synapse.visibility import filter_events_for_client |
37 | 28 |
|
38 | 29 | if TYPE_CHECKING: |
@@ -181,40 +172,6 @@ async def get_relations( |
181 | 172 |
|
182 | 173 | return return_value |
183 | 174 |
|
184 | | - async def get_relations_for_event( |
185 | | - self, |
186 | | - event_id: str, |
187 | | - event: EventBase, |
188 | | - room_id: str, |
189 | | - relation_type: str, |
190 | | - ignored_users: FrozenSet[str] = frozenset(), |
191 | | - ) -> Tuple[List[_RelatedEvent], Optional[StreamToken]]: |
192 | | - """Get a list of events which relate to an event, ordered by topological ordering. |
193 | | -
|
194 | | - Args: |
195 | | - event_id: Fetch events that relate to this event ID. |
196 | | - event: The matching EventBase to event_id. |
197 | | - room_id: The room the event belongs to. |
198 | | - relation_type: The type of relation. |
199 | | - ignored_users: The users ignored by the requesting user. |
200 | | -
|
201 | | - Returns: |
202 | | - List of event IDs that match relations requested. The rows are of |
203 | | - the form `{"event_id": "..."}`. |
204 | | - """ |
205 | | - |
206 | | - # Call the underlying storage method, which is cached. |
207 | | - related_events, next_token = await self._main_store.get_relations_for_event( |
208 | | - event_id, event, room_id, relation_type, direction="f" |
209 | | - ) |
210 | | - |
211 | | - # Filter out ignored users and convert to the expected format. |
212 | | - related_events = [ |
213 | | - event for event in related_events if event.sender not in ignored_users |
214 | | - ] |
215 | | - |
216 | | - return related_events, next_token |
217 | | - |
218 | 175 | async def redact_events_related_to( |
219 | 176 | self, |
220 | 177 | requester: Requester, |
@@ -329,6 +286,46 @@ async def get_annotations_for_events( |
329 | 286 |
|
330 | 287 | return filtered_results |
331 | 288 |
|
| 289 | + async def get_references_for_events( |
| 290 | + self, event_ids: Collection[str], ignored_users: FrozenSet[str] = frozenset() |
| 291 | + ) -> Dict[str, List[_RelatedEvent]]: |
| 292 | + """Get a list of references to the given events. |
| 293 | +
|
| 294 | + Args: |
| 295 | + event_ids: Fetch events that relate to this event ID. |
| 296 | + ignored_users: The users ignored by the requesting user. |
| 297 | +
|
| 298 | + Returns: |
| 299 | + A map of event IDs to a list related events. |
| 300 | + """ |
| 301 | + |
| 302 | + related_events = await self._main_store.get_references_for_events(event_ids) |
| 303 | + |
| 304 | + # Avoid additional logic if there are no ignored users. |
| 305 | + if not ignored_users: |
| 306 | + return { |
| 307 | + event_id: results |
| 308 | + for event_id, results in related_events.items() |
| 309 | + if results |
| 310 | + } |
| 311 | + |
| 312 | + # Filter out ignored users. |
| 313 | + results = {} |
| 314 | + for event_id, events in related_events.items(): |
| 315 | + # If no references, skip. |
| 316 | + if not events: |
| 317 | + continue |
| 318 | + |
| 319 | + # Filter ignored users out. |
| 320 | + events = [event for event in events if event.sender not in ignored_users] |
| 321 | + # If there are no events left, skip this event. |
| 322 | + if not events: |
| 323 | + continue |
| 324 | + |
| 325 | + results[event_id] = events |
| 326 | + |
| 327 | + return results |
| 328 | + |
332 | 329 | async def _get_threads_for_events( |
333 | 330 | self, |
334 | 331 | events_by_id: Dict[str, EventBase], |
@@ -412,14 +409,18 @@ async def _get_threads_for_events( |
412 | 409 | if event is None: |
413 | 410 | continue |
414 | 411 |
|
415 | | - potential_events, _ = await self.get_relations_for_event( |
416 | | - event_id, |
417 | | - event, |
418 | | - room_id, |
419 | | - RelationTypes.THREAD, |
420 | | - ignored_users, |
| 412 | + # Attempt to find another event to use as the latest event. |
| 413 | + potential_events, _ = await self._main_store.get_relations_for_event( |
| 414 | + event_id, event, room_id, RelationTypes.THREAD, direction="f" |
421 | 415 | ) |
422 | 416 |
|
| 417 | + # Filter out ignored users. |
| 418 | + potential_events = [ |
| 419 | + event |
| 420 | + for event in potential_events |
| 421 | + if event.sender not in ignored_users |
| 422 | + ] |
| 423 | + |
423 | 424 | # If all found events are from ignored users, do not include |
424 | 425 | # a summary of the thread. |
425 | 426 | if not potential_events: |
@@ -534,27 +535,16 @@ async def get_bundled_aggregations( |
534 | 535 | "chunk": annotations |
535 | 536 | } |
536 | 537 |
|
537 | | - # Fetch other relations per event. |
538 | | - for event in events_by_id.values(): |
539 | | - # Fetch any references to bundle with this event. |
540 | | - references, next_token = await self.get_relations_for_event( |
541 | | - event.event_id, |
542 | | - event, |
543 | | - event.room_id, |
544 | | - RelationTypes.REFERENCE, |
545 | | - ignored_users=ignored_users, |
546 | | - ) |
| 538 | + # Fetch any references to bundle with this event. |
| 539 | + references_by_event_id = await self.get_references_for_events( |
| 540 | + events_by_id.keys(), ignored_users=ignored_users |
| 541 | + ) |
| 542 | + for event_id, references in references_by_event_id.items(): |
547 | 543 | if references: |
548 | | - aggregations = results.setdefault(event.event_id, BundledAggregations()) |
549 | | - aggregations.references = { |
| 544 | + results.setdefault(event_id, BundledAggregations()).references = { |
550 | 545 | "chunk": [{"event_id": ev.event_id} for ev in references] |
551 | 546 | } |
552 | 547 |
|
553 | | - if next_token: |
554 | | - aggregations.references["next_batch"] = await next_token.to_string( |
555 | | - self._main_store |
556 | | - ) |
557 | | - |
558 | 548 | # Fetch any edits (but not for redacted events). |
559 | 549 | # |
560 | 550 | # Note that there is no use in limiting edits by ignored users since the |
@@ -600,7 +590,7 @@ async def get_threads( |
600 | 590 | room_id, requester, allow_departed_users=True |
601 | 591 | ) |
602 | 592 |
|
603 | | - # Note that ignored users are not passed into get_relations_for_event |
| 593 | + # Note that ignored users are not passed into get_threads |
604 | 594 | # below. Ignored users are handled in filter_events_for_client (and by |
605 | 595 | # not passing them in here we should get a better cache hit rate). |
606 | 596 | thread_roots, next_batch = await self._main_store.get_threads( |
|
0 commit comments