mirror of
https://github.com/element-hq/synapse.git
synced 2026-08-14 15:50:19 +00:00
Fetch a room's hierarchy caches concurrently on the cold path
The cached fast path serialised its per-room lookups (is_partial_state_room, then the hierarchy state cache fill, then room version and stats), which undid the traversal-level prefetch parallelism on a cold cache under latency. Gather them concurrently instead, warming the room-stats and room-version caches that the rest of the path reads. Since the partial-state check now races the cache fill, drop the cached hierarchy state again when the room turns out to be partial-stated, and register get_room_hierarchy_state in _invalidate_state_caches(_all) so state resets and un-partial-stating invalidate it too.
This commit is contained in:
@@ -50,7 +50,8 @@ from synapse.logging.context import make_deferred_yieldable, run_in_background
|
||||
from synapse.storage.databases.main.state import RoomHierarchyState
|
||||
from synapse.types import JsonDict, JsonMapping, Requester, StateMap, StrCollection
|
||||
from synapse.types.state import StateFilter
|
||||
from synapse.util.async_helpers import yieldable_gather_results
|
||||
from synapse.util import unwrapFirstError
|
||||
from synapse.util.async_helpers import gather_results, yieldable_gather_results
|
||||
from synapse.util.caches.response_cache import ResponseCache
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -581,15 +582,46 @@ class RoomSummaryHandler:
|
||||
Returns:
|
||||
A room entry if the room should be returned. None, otherwise.
|
||||
"""
|
||||
|
||||
# Fast path: serve the entry entirely from the cached room hierarchy
|
||||
# state + room stats (both invalidated when the underlying data
|
||||
# changes), so a warm request does no DB work at all. Partial-state
|
||||
# rooms fall back to the uncached path, as their cached current state
|
||||
# may be incomplete; unknown rooms fall back for the pending-invite
|
||||
# handling.
|
||||
hierarchy_state = None
|
||||
if not await self._store.is_partial_state_room(room_id):
|
||||
hierarchy_state = await self._store.get_room_hierarchy_state(room_id)
|
||||
#
|
||||
# The per-room lookups are independent, so run them (including warming
|
||||
# the room-stats / room-version caches read later in this path)
|
||||
# concurrently: on a cold cache a serial chain here would otherwise
|
||||
# undo the traversal-level parallelism on latency-bound deployments.
|
||||
async def prime_room_version() -> None:
|
||||
try:
|
||||
await self._store.get_room_version(room_id)
|
||||
except (NotFoundError, UnsupportedRoomVersionError):
|
||||
pass
|
||||
|
||||
is_partial_state, hierarchy_state, _, _ = await make_deferred_yieldable(
|
||||
gather_results(
|
||||
(
|
||||
# NB lambdas as run_in_background's typing rejects @cached methods.
|
||||
run_in_background(
|
||||
lambda: self._store.is_partial_state_room(room_id)
|
||||
),
|
||||
run_in_background(
|
||||
lambda: self._store.get_room_hierarchy_state(room_id)
|
||||
),
|
||||
run_in_background(lambda: self._store.get_room_with_stats(room_id)),
|
||||
run_in_background(prime_room_version),
|
||||
),
|
||||
consumeErrors=True,
|
||||
)
|
||||
).addErrback(unwrapFirstError)
|
||||
if is_partial_state:
|
||||
# The value cached just now may have been computed from partial
|
||||
# state: drop it and use the uncached path (which resolves state
|
||||
# via the storage controllers).
|
||||
self._store.get_room_hierarchy_state.invalidate((room_id,))
|
||||
hierarchy_state = None
|
||||
if hierarchy_state is None:
|
||||
return await self._summarize_local_room_uncached(
|
||||
requester,
|
||||
|
||||
@@ -139,6 +139,7 @@ class SQLBaseStore(metaclass=ABCMeta):
|
||||
self._attempt_to_invalidate_cache("get_partial_current_state_ids", (room_id,))
|
||||
self._attempt_to_invalidate_cache("get_room_type", (room_id,))
|
||||
self._attempt_to_invalidate_cache("get_room_encryption", (room_id,))
|
||||
self._attempt_to_invalidate_cache("get_room_hierarchy_state", (room_id,))
|
||||
self._attempt_to_invalidate_cache(
|
||||
"get_sliding_sync_rooms_for_user_from_membership_snapshots", None
|
||||
)
|
||||
@@ -171,6 +172,7 @@ class SQLBaseStore(metaclass=ABCMeta):
|
||||
self._attempt_to_invalidate_cache("get_room_summary", (room_id,))
|
||||
self._attempt_to_invalidate_cache("get_room_type", (room_id,))
|
||||
self._attempt_to_invalidate_cache("get_room_encryption", (room_id,))
|
||||
self._attempt_to_invalidate_cache("get_room_hierarchy_state", (room_id,))
|
||||
self._attempt_to_invalidate_cache(
|
||||
"get_sliding_sync_rooms_for_user_from_membership_snapshots", None
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user