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

Commit f5aaa55

Browse files
author
David Robertson
authored
Add new columns tracking when we partial-joined (#13892)
1 parent 87fe9db commit f5aaa55

File tree

4 files changed

+87
-3
lines changed

4 files changed

+87
-3
lines changed

changelog.d/13892.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Faster remote room joins: record _when_ we first partial-join to a room.

synapse/handlers/federation.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,11 @@ async def do_invite_join(
581581
# Mark the room as having partial state.
582582
# The background process is responsible for unmarking this flag,
583583
# even if the join fails.
584-
await self.store.store_partial_state_room(room_id, ret.servers_in_room)
584+
await self.store.store_partial_state_room(
585+
room_id=room_id,
586+
servers=ret.servers_in_room,
587+
device_lists_stream_id=self.store.get_device_stream_token(),
588+
)
585589

586590
try:
587591
max_stream_id = (
@@ -606,6 +610,14 @@ async def do_invite_join(
606610
room_id,
607611
)
608612
raise LimitExceededError(msg=e.msg, errcode=e.errcode, retry_after_ms=0)
613+
else:
614+
# Record the join event id for future use (when we finish the full
615+
# join). We have to do this after persisting the event to keep foreign
616+
# key constraints intact.
617+
if ret.partial_state:
618+
await self.store.write_partial_state_rooms_join_event_id(
619+
room_id, event.event_id
620+
)
609621
finally:
610622
# Always kick off the background process that asynchronously fetches
611623
# state for the room.

synapse/storage/databases/main/room.py

+50-2
Original file line numberDiff line numberDiff line change
@@ -1777,28 +1777,46 @@ async def store_partial_state_room(
17771777
self,
17781778
room_id: str,
17791779
servers: Collection[str],
1780+
device_lists_stream_id: int,
17801781
) -> None:
1781-
"""Mark the given room as containing events with partial state
1782+
"""Mark the given room as containing events with partial state.
1783+
1784+
We also store additional data that describes _when_ we first partial-joined this
1785+
room, which helps us to keep other homeservers in sync when we finally fully
1786+
join this room.
1787+
1788+
We do not include a `join_event_id` here---we need to wait for the join event
1789+
to be persisted first.
17821790
17831791
Args:
17841792
room_id: the ID of the room
17851793
servers: other servers known to be in the room
1794+
device_lists_stream_id: the device_lists stream ID at the time when we first
1795+
joined the room.
17861796
"""
17871797
await self.db_pool.runInteraction(
17881798
"store_partial_state_room",
17891799
self._store_partial_state_room_txn,
17901800
room_id,
17911801
servers,
1802+
device_lists_stream_id,
17921803
)
17931804

17941805
def _store_partial_state_room_txn(
1795-
self, txn: LoggingTransaction, room_id: str, servers: Collection[str]
1806+
self,
1807+
txn: LoggingTransaction,
1808+
room_id: str,
1809+
servers: Collection[str],
1810+
device_lists_stream_id: int,
17961811
) -> None:
17971812
DatabasePool.simple_insert_txn(
17981813
txn,
17991814
table="partial_state_rooms",
18001815
values={
18011816
"room_id": room_id,
1817+
"device_lists_stream_id": device_lists_stream_id,
1818+
# To be updated later once the join event is persisted.
1819+
"join_event_id": None,
18021820
},
18031821
)
18041822
DatabasePool.simple_insert_many_txn(
@@ -1809,6 +1827,36 @@ def _store_partial_state_room_txn(
18091827
)
18101828
self._invalidate_cache_and_stream(txn, self.is_partial_state_room, (room_id,))
18111829

1830+
async def write_partial_state_rooms_join_event_id(
1831+
self,
1832+
room_id: str,
1833+
join_event_id: str,
1834+
) -> None:
1835+
"""Record the join event which resulted from a partial join.
1836+
1837+
We do this separately to `store_partial_state_room` because we need to wait for
1838+
the join event to be persisted. Otherwise we violate a foreign key constraint.
1839+
"""
1840+
await self.db_pool.runInteraction(
1841+
"write_partial_state_rooms_join_event_id",
1842+
self._write_partial_state_rooms_join_event_id,
1843+
room_id,
1844+
join_event_id,
1845+
)
1846+
1847+
def _write_partial_state_rooms_join_event_id(
1848+
self,
1849+
txn: LoggingTransaction,
1850+
room_id: str,
1851+
join_event_id: str,
1852+
) -> None:
1853+
DatabasePool.simple_update_txn(
1854+
txn,
1855+
table="partial_state_rooms",
1856+
keyvalues={"room_id": room_id},
1857+
updatevalues={"join_event_id": join_event_id},
1858+
)
1859+
18121860
async def maybe_store_room_on_outlier_membership(
18131861
self, room_id: str, room_version: RoomVersion
18141862
) -> None:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* Copyright 2022 The Matrix.org Foundation C.I.C
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
-- To ensure we correctly notify other homeservers about device list changes from our
17+
-- users after a partial join transitions to a full join, we need to know when we began
18+
-- the partial join. For now it's sufficient to know the device_list stream_id at the
19+
-- time of the partial join, and the join event created for us during a partial join.
20+
--
21+
-- Both columns are backwards compatible.
22+
ALTER TABLE partial_state_rooms ADD COLUMN device_lists_stream_id BIGINT NOT NULL DEFAULT 0;
23+
ALTER TABLE partial_state_rooms ADD COLUMN join_event_id TEXT REFERENCES events(event_id);

0 commit comments

Comments
 (0)