-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Improve event caching code #10119
Improve event caching code #10119
Changes from 1 commit
1a77fe3
27e4f5c
d472a08
5afe3d2
b292141
9d6a77b
918f7be
d120766
059c85e
a8b777d
af02613
0f9e19c
3d46c4a
213c5c0
b095d21
8ea267a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
|
||
import logging | ||
import threading | ||
import weakref | ||
from typing import ( | ||
Collection, | ||
Container, | ||
|
@@ -174,6 +175,10 @@ def __init__(self, database: DatabasePool, db_conn, hs): | |
# Dict[str, _EventCacheEntry]. | ||
self._current_event_fetches: Dict[str, ObservableDeferred] = {} | ||
|
||
# We keep track of the events we have currently loaded in memory so that | ||
# we can reuse them even if they've been evicted from the cache. | ||
self._event_ref: Dict[str, EventBase] = weakref.WeakValueDictionary() | ||
|
||
self._event_fetch_lock = threading.Condition() | ||
self._event_fetch_list = [] | ||
self._event_fetch_ongoing = 0 | ||
|
@@ -588,6 +593,8 @@ async def _get_events_from_cache_or_db( | |
|
||
def _invalidate_get_event_cache(self, event_id): | ||
self._get_event_cache.invalidate((event_id,)) | ||
self._event_ref.pop(event_id, None) | ||
self._current_event_fetches.pop(event_id, None) | ||
|
||
def _get_events_from_cache( | ||
self, events: Iterable[str], update_metrics: bool = True | ||
|
@@ -601,13 +608,34 @@ def _get_events_from_cache( | |
event_map = {} | ||
|
||
for event_id in events: | ||
# First check if its in the event cache | ||
erikjohnston marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ret = self._get_event_cache.get( | ||
(event_id,), None, update_metrics=update_metrics | ||
) | ||
if not ret: | ||
continue | ||
if ret: | ||
event_map[event_id] = ret | ||
|
||
# Otherwise check if we still have the event in memory. | ||
event = self._event_ref.get(event_id) | ||
if event: | ||
redacted_event = None | ||
erikjohnston marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if event.internal_metadata.redacted_by is not None: | ||
# The event has been redacted, so we generate a redacted | ||
# version. | ||
redacted_event = prune_event(event) | ||
redacted_event.unsigned[ | ||
"redacted_by" | ||
] = event.internal_metadata.redacted_by | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we not need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code will be split out into its own PR. |
||
|
||
cache_entry = _EventCacheEntry( | ||
event=event, | ||
redacted_event=redacted_event, | ||
) | ||
event_map[event_id] = cache_entry | ||
|
||
event_map[event_id] = ret | ||
# We add the entry back into the cache as we want to keep | ||
# recently queried events in the cache. | ||
self._get_event_cache.set((event_id,), cache_entry) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we refactor the similar code in For example: have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code will be split out into its own PR. |
||
|
||
return event_map | ||
|
||
|
@@ -877,13 +905,20 @@ async def _get_events_from_db( | |
original_ev, redactions, event_map | ||
) | ||
|
||
if redacted_event: | ||
original_ev.internal_metadata.redacted_by = redacted_event.unsigned[ | ||
"redacted_by" | ||
] | ||
|
||
cache_entry = _EventCacheEntry( | ||
event=original_ev, redacted_event=redacted_event | ||
) | ||
|
||
self._get_event_cache.set((event_id,), cache_entry) | ||
result_map[event_id] = cache_entry | ||
|
||
self._event_ref[event_id] = original_ev | ||
|
||
return result_map | ||
|
||
async def _enqueue_events(self, events): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm super dubious about stuffing more things in here that don't form part of the
internal_metadata
column in the database.Should we start a new attrs class for things like this,
stream_ordering
andoutlier
? (it also looks likebefore
,after
,order
might fall into the same category).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also: it seems confusing to have both a
redacted_by
and aredacted
property.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code will be split out into its own PR.