|
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