Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/19390.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Provide remote servers a way to find out about an event created during the remote join handshake. Contributed by @FrenchGithubUser and @jason-famedly @ Famedly.
25 changes: 25 additions & 0 deletions synapse/federation/federation_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,10 @@ async def on_send_join_request(
event, context = await self._on_send_membership_event(
origin, content, Membership.JOIN, room_id
)
# Collect this now, the internal metadata of event(which should have it) doesn't
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is quite difficult to read.

And why not query this close to where it's used, below?

stream_ordering_of_join = (
await self.store.get_current_room_stream_token_for_room_id(room_id)
Comment on lines +761 to +763
)

prev_state_ids = await context.get_prev_state_ids()

Expand Down Expand Up @@ -798,6 +802,27 @@ async def on_send_join_request(
"members_omitted": caller_supports_partial_state,
}

# Check the forward extremities for the room here. If there is more than one, it
# is likely that another event was created in the room during the
# make_join/send_join handshake. Without being able to determine how long until
# the next event will be created that references this 'missing event',
# proactively send a dummy extensible event that ties these forward extremities
# together. The remote server should search out this missing event on its own.
#
# By not sending the 'missing event' directly, the stream ordering for it will
# be consistent between servers(in that it technically was created before the
# join itself).

forward_extremities = await self.store._get_forward_extremeties_for_room(
room_id, stream_ordering_of_join.get_max_stream_pos()
)

if len(forward_extremities) > 1:
# I do not feel it is necessary to set this onto the FederationServer class
# itself. Its likelihood of being used is extremely low. Make it on-demand
_creation_handler = self.hs.get_event_creation_handler()
await _creation_handler._send_dummy_events_to_patch_room(room_id)

Comment on lines +821 to +826
Comment on lines +805 to +826
if servers_in_room is not None:
resp["servers_in_room"] = list(servers_in_room)

Expand Down
34 changes: 31 additions & 3 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -2220,7 +2220,36 @@ async def _send_dummy_events_to_fill_extremities(self) -> None:
now = self.clock.time_msec()
self._rooms_to_exclude_from_dummy_event_insertion[room_id] = now

async def _send_dummy_event_for_room(self, room_id: str) -> bool:
async def _send_dummy_events_to_patch_room(self, room_id: str) -> None:
"""
Send a dummy event into this room to patch in a missed forward extremity.
This should only be triggered during a remote join if there was a forward
extremity that occurred during the make_join/send_join handshake.
"""
async with self._worker_lock_handler.acquire_read_write_lock(
NEW_EVENT_DURING_PURGE_LOCK_NAME, room_id, write=False
):
dummy_event_sent = await self._send_dummy_event_for_room(
room_id, proactively_send=True
)

if not dummy_event_sent:
# Did not find a valid user in the room, so remove from future attempts
# Exclusion is time limited, so the room will be rechecked in the future
# dependent on _DUMMY_EVENT_ROOM_EXCLUSION_EXPIRY
logger.info(
"Failed to send dummy event into room %s. Will exclude it from "
"future attempts until cache expires",
room_id,
)
# This mapping is room_id -> time of last attempt(in ms)
self._rooms_to_exclude_from_dummy_event_insertion[room_id] = (
self.clock.time_msec()
)
Comment on lines +2239 to +2251
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth waiting an trying again if the room will move on in the meantime, and new events will likely be sent?


async def _send_dummy_event_for_room(
self, room_id: str, proactively_send: bool = False
) -> bool:
"""Attempt to send a dummy event for the given room.

Args:
Expand Down Expand Up @@ -2252,8 +2281,7 @@ async def _send_dummy_event_for_room(self, room_id: str) -> bool:
},
)
context = await unpersisted_context.persist(event)

event.internal_metadata.proactively_send = False
event.internal_metadata.proactively_send = proactively_send

# Since this is a dummy-event it is OK if it is sent by a
# shadow-banned user.
Expand Down
Loading