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

Commit

Permalink
Fix a bug where the joined hosts for a given event were not being pro…
Browse files Browse the repository at this point in the history
…perly cached (#14125)
  • Loading branch information
H-Shay authored Oct 12, 2022
1 parent e6e876b commit b6baa46
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 45 deletions.
1 change: 1 addition & 0 deletions changelog.d/14125.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a bug introduced in v1.69.0rc1 where the joined hosts for a given event were not being properly cached.
4 changes: 3 additions & 1 deletion synapse/handlers/federation_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,9 @@ async def on_send_membership_event(

# First, precalculate the joined hosts so that the federation sender doesn't
# need to.
await self._event_creation_handler.cache_joined_hosts_for_event(event, context)
await self._event_creation_handler.cache_joined_hosts_for_events(
[(event, context)]
)

await self._check_for_soft_fail(event, context=context, origin=origin)
await self._run_push_actions_and_persist_event(event, context)
Expand Down
91 changes: 47 additions & 44 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,7 @@ async def handle_new_client_event(
extra_users=extra_users,
),
run_in_background(
self.cache_joined_hosts_for_event, event, context
self.cache_joined_hosts_for_events, events_and_context
).addErrback(
log_failure, "cache_joined_hosts_for_event failed"
),
Expand Down Expand Up @@ -1491,62 +1491,65 @@ async def _persist_events(
await self.store.remove_push_actions_from_staging(event.event_id)
raise

async def cache_joined_hosts_for_event(
self, event: EventBase, context: EventContext
async def cache_joined_hosts_for_events(
self, events_and_context: List[Tuple[EventBase, EventContext]]
) -> None:
"""Precalculate the joined hosts at the event, when using Redis, so that
"""Precalculate the joined hosts at each of the given events, when using Redis, so that
external federation senders don't have to recalculate it themselves.
"""

if not self._external_cache.is_enabled():
return

# If external cache is enabled we should always have this.
assert self._external_cache_joined_hosts_updates is not None
for event, _ in events_and_context:
if not self._external_cache.is_enabled():
return

# We actually store two mappings, event ID -> prev state group,
# state group -> joined hosts, which is much more space efficient
# than event ID -> joined hosts.
#
# Note: We have to cache event ID -> prev state group, as we don't
# store that in the DB.
#
# Note: We set the state group -> joined hosts cache if it hasn't been
# set for a while, so that the expiry time is reset.
# If external cache is enabled we should always have this.
assert self._external_cache_joined_hosts_updates is not None

state_entry = await self.state.resolve_state_groups_for_events(
event.room_id, event_ids=event.prev_event_ids()
)
# We actually store two mappings, event ID -> prev state group,
# state group -> joined hosts, which is much more space efficient
# than event ID -> joined hosts.
#
# Note: We have to cache event ID -> prev state group, as we don't
# store that in the DB.
#
# Note: We set the state group -> joined hosts cache if it hasn't been
# set for a while, so that the expiry time is reset.

if state_entry.state_group:
await self._external_cache.set(
"event_to_prev_state_group",
event.event_id,
state_entry.state_group,
expiry_ms=60 * 60 * 1000,
state_entry = await self.state.resolve_state_groups_for_events(
event.room_id, event_ids=event.prev_event_ids()
)

if state_entry.state_group in self._external_cache_joined_hosts_updates:
return
if state_entry.state_group:
await self._external_cache.set(
"event_to_prev_state_group",
event.event_id,
state_entry.state_group,
expiry_ms=60 * 60 * 1000,
)

state = await state_entry.get_state(
self._storage_controllers.state, StateFilter.all()
)
with opentracing.start_active_span("get_joined_hosts"):
joined_hosts = await self.store.get_joined_hosts(
event.room_id, state, state_entry
if state_entry.state_group in self._external_cache_joined_hosts_updates:
return

state = await state_entry.get_state(
self._storage_controllers.state, StateFilter.all()
)
with opentracing.start_active_span("get_joined_hosts"):
joined_hosts = await self.store.get_joined_hosts(
event.room_id, state, state_entry
)

# Note that the expiry times must be larger than the expiry time in
# _external_cache_joined_hosts_updates.
await self._external_cache.set(
"get_joined_hosts",
str(state_entry.state_group),
list(joined_hosts),
expiry_ms=60 * 60 * 1000,
)
# Note that the expiry times must be larger than the expiry time in
# _external_cache_joined_hosts_updates.
await self._external_cache.set(
"get_joined_hosts",
str(state_entry.state_group),
list(joined_hosts),
expiry_ms=60 * 60 * 1000,
)

self._external_cache_joined_hosts_updates[state_entry.state_group] = None
self._external_cache_joined_hosts_updates[
state_entry.state_group
] = None

async def _validate_canonical_alias(
self,
Expand Down

0 comments on commit b6baa46

Please sign in to comment.