Skip to content

Commit c856ae4

Browse files
Refactor SyncResultBuilder assembly to its own function (#17202)
We will re-use `get_sync_result_builder(...)` in #17167 Split out from #17167
1 parent fe07995 commit c856ae4

File tree

2 files changed

+149
-116
lines changed

2 files changed

+149
-116
lines changed

changelog.d/17202.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Refactor `SyncResultBuilder` assembly to its own function.

synapse/handlers/sync.py

+148-116
Original file line numberDiff line numberDiff line change
@@ -1569,12 +1569,158 @@ async def generate_sync_result(
15691569
# See https://github.com/matrix-org/matrix-doc/issues/1144
15701570
raise NotImplementedError()
15711571

1572+
sync_result_builder = await self.get_sync_result_builder(
1573+
sync_config,
1574+
since_token,
1575+
full_state,
1576+
)
1577+
1578+
logger.debug(
1579+
"Calculating sync response for %r between %s and %s",
1580+
sync_config.user,
1581+
sync_result_builder.since_token,
1582+
sync_result_builder.now_token,
1583+
)
1584+
1585+
logger.debug("Fetching account data")
1586+
1587+
# Global account data is included if it is not filtered out.
1588+
if not sync_config.filter_collection.blocks_all_global_account_data():
1589+
await self._generate_sync_entry_for_account_data(sync_result_builder)
1590+
1591+
# Presence data is included if the server has it enabled and not filtered out.
1592+
include_presence_data = bool(
1593+
self.hs_config.server.presence_enabled
1594+
and not sync_config.filter_collection.blocks_all_presence()
1595+
)
1596+
# Device list updates are sent if a since token is provided.
1597+
include_device_list_updates = bool(since_token and since_token.device_list_key)
1598+
1599+
# If we do not care about the rooms or things which depend on the room
1600+
# data (namely presence and device list updates), then we can skip
1601+
# this process completely.
1602+
device_lists = DeviceListUpdates()
1603+
if (
1604+
not sync_result_builder.sync_config.filter_collection.blocks_all_rooms()
1605+
or include_presence_data
1606+
or include_device_list_updates
1607+
):
1608+
logger.debug("Fetching room data")
1609+
1610+
# Note that _generate_sync_entry_for_rooms sets sync_result_builder.joined, which
1611+
# is used in calculate_user_changes below.
1612+
(
1613+
newly_joined_rooms,
1614+
newly_left_rooms,
1615+
) = await self._generate_sync_entry_for_rooms(sync_result_builder)
1616+
1617+
# Work out which users have joined or left rooms we're in. We use this
1618+
# to build the presence and device_list parts of the sync response in
1619+
# `_generate_sync_entry_for_presence` and
1620+
# `_generate_sync_entry_for_device_list` respectively.
1621+
if include_presence_data or include_device_list_updates:
1622+
# This uses the sync_result_builder.joined which is set in
1623+
# `_generate_sync_entry_for_rooms`, if that didn't find any joined
1624+
# rooms for some reason it is a no-op.
1625+
(
1626+
newly_joined_or_invited_or_knocked_users,
1627+
newly_left_users,
1628+
) = sync_result_builder.calculate_user_changes()
1629+
1630+
if include_presence_data:
1631+
logger.debug("Fetching presence data")
1632+
await self._generate_sync_entry_for_presence(
1633+
sync_result_builder,
1634+
newly_joined_rooms,
1635+
newly_joined_or_invited_or_knocked_users,
1636+
)
1637+
1638+
if include_device_list_updates:
1639+
device_lists = await self._generate_sync_entry_for_device_list(
1640+
sync_result_builder,
1641+
newly_joined_rooms=newly_joined_rooms,
1642+
newly_joined_or_invited_or_knocked_users=newly_joined_or_invited_or_knocked_users,
1643+
newly_left_rooms=newly_left_rooms,
1644+
newly_left_users=newly_left_users,
1645+
)
1646+
1647+
logger.debug("Fetching to-device data")
1648+
await self._generate_sync_entry_for_to_device(sync_result_builder)
1649+
1650+
logger.debug("Fetching OTK data")
1651+
device_id = sync_config.device_id
1652+
one_time_keys_count: JsonMapping = {}
1653+
unused_fallback_key_types: List[str] = []
1654+
if device_id:
1655+
# TODO: We should have a way to let clients differentiate between the states of:
1656+
# * no change in OTK count since the provided since token
1657+
# * the server has zero OTKs left for this device
1658+
# Spec issue: https://github.com/matrix-org/matrix-doc/issues/3298
1659+
one_time_keys_count = await self.store.count_e2e_one_time_keys(
1660+
user_id, device_id
1661+
)
1662+
unused_fallback_key_types = list(
1663+
await self.store.get_e2e_unused_fallback_key_types(user_id, device_id)
1664+
)
1665+
1666+
num_events = 0
1667+
1668+
# debug for https://github.com/matrix-org/synapse/issues/9424
1669+
for joined_room in sync_result_builder.joined:
1670+
num_events += len(joined_room.timeline.events)
1671+
1672+
log_kv(
1673+
{
1674+
"joined_rooms_in_result": len(sync_result_builder.joined),
1675+
"events_in_result": num_events,
1676+
}
1677+
)
1678+
1679+
logger.debug("Sync response calculation complete")
1680+
return SyncResult(
1681+
presence=sync_result_builder.presence,
1682+
account_data=sync_result_builder.account_data,
1683+
joined=sync_result_builder.joined,
1684+
invited=sync_result_builder.invited,
1685+
knocked=sync_result_builder.knocked,
1686+
archived=sync_result_builder.archived,
1687+
to_device=sync_result_builder.to_device,
1688+
device_lists=device_lists,
1689+
device_one_time_keys_count=one_time_keys_count,
1690+
device_unused_fallback_key_types=unused_fallback_key_types,
1691+
next_batch=sync_result_builder.now_token,
1692+
)
1693+
1694+
async def get_sync_result_builder(
1695+
self,
1696+
sync_config: SyncConfig,
1697+
since_token: Optional[StreamToken] = None,
1698+
full_state: bool = False,
1699+
) -> "SyncResultBuilder":
1700+
"""
1701+
Assemble a `SyncResultBuilder` with all of the initial context to
1702+
start building up the sync response:
1703+
1704+
- Membership changes between the last sync and the current sync.
1705+
- Joined room IDs (minus any rooms to exclude).
1706+
- Rooms that became fully-stated/un-partial stated since the last sync.
1707+
1708+
Args:
1709+
sync_config: Config/info necessary to process the sync request.
1710+
since_token: The point in the stream to sync from.
1711+
full_state: Whether to return the full state for each room.
1712+
1713+
Returns:
1714+
`SyncResultBuilder` ready to start generating parts of the sync response.
1715+
"""
1716+
user_id = sync_config.user.to_string()
1717+
15721718
# Note: we get the users room list *before* we get the current token, this
15731719
# avoids checking back in history if rooms are joined after the token is fetched.
15741720
token_before_rooms = self.event_sources.get_current_token()
15751721
mutable_joined_room_ids = set(await self.store.get_rooms_for_user(user_id))
15761722

1577-
# NB: The now_token gets changed by some of the generate_sync_* methods,
1723+
# NB: The `now_token` gets changed by some of the `generate_sync_*` methods,
15781724
# this is due to some of the underlying streams not supporting the ability
15791725
# to query up to a given point.
15801726
# Always use the `now_token` in `SyncResultBuilder`
@@ -1675,13 +1821,6 @@ async def generate_sync_result(
16751821
if room_id not in mutable_rooms_to_exclude
16761822
)
16771823

1678-
logger.debug(
1679-
"Calculating sync response for %r between %s and %s",
1680-
sync_config.user,
1681-
since_token,
1682-
now_token,
1683-
)
1684-
16851824
sync_result_builder = SyncResultBuilder(
16861825
sync_config,
16871826
full_state,
@@ -1693,114 +1832,7 @@ async def generate_sync_result(
16931832
membership_change_events=membership_change_events,
16941833
)
16951834

1696-
logger.debug("Fetching account data")
1697-
1698-
# Global account data is included if it is not filtered out.
1699-
if not sync_config.filter_collection.blocks_all_global_account_data():
1700-
await self._generate_sync_entry_for_account_data(sync_result_builder)
1701-
1702-
# Presence data is included if the server has it enabled and not filtered out.
1703-
include_presence_data = bool(
1704-
self.hs_config.server.presence_enabled
1705-
and not sync_config.filter_collection.blocks_all_presence()
1706-
)
1707-
# Device list updates are sent if a since token is provided.
1708-
include_device_list_updates = bool(since_token and since_token.device_list_key)
1709-
1710-
# If we do not care about the rooms or things which depend on the room
1711-
# data (namely presence and device list updates), then we can skip
1712-
# this process completely.
1713-
device_lists = DeviceListUpdates()
1714-
if (
1715-
not sync_result_builder.sync_config.filter_collection.blocks_all_rooms()
1716-
or include_presence_data
1717-
or include_device_list_updates
1718-
):
1719-
logger.debug("Fetching room data")
1720-
1721-
# Note that _generate_sync_entry_for_rooms sets sync_result_builder.joined, which
1722-
# is used in calculate_user_changes below.
1723-
(
1724-
newly_joined_rooms,
1725-
newly_left_rooms,
1726-
) = await self._generate_sync_entry_for_rooms(sync_result_builder)
1727-
1728-
# Work out which users have joined or left rooms we're in. We use this
1729-
# to build the presence and device_list parts of the sync response in
1730-
# `_generate_sync_entry_for_presence` and
1731-
# `_generate_sync_entry_for_device_list` respectively.
1732-
if include_presence_data or include_device_list_updates:
1733-
# This uses the sync_result_builder.joined which is set in
1734-
# `_generate_sync_entry_for_rooms`, if that didn't find any joined
1735-
# rooms for some reason it is a no-op.
1736-
(
1737-
newly_joined_or_invited_or_knocked_users,
1738-
newly_left_users,
1739-
) = sync_result_builder.calculate_user_changes()
1740-
1741-
if include_presence_data:
1742-
logger.debug("Fetching presence data")
1743-
await self._generate_sync_entry_for_presence(
1744-
sync_result_builder,
1745-
newly_joined_rooms,
1746-
newly_joined_or_invited_or_knocked_users,
1747-
)
1748-
1749-
if include_device_list_updates:
1750-
device_lists = await self._generate_sync_entry_for_device_list(
1751-
sync_result_builder,
1752-
newly_joined_rooms=newly_joined_rooms,
1753-
newly_joined_or_invited_or_knocked_users=newly_joined_or_invited_or_knocked_users,
1754-
newly_left_rooms=newly_left_rooms,
1755-
newly_left_users=newly_left_users,
1756-
)
1757-
1758-
logger.debug("Fetching to-device data")
1759-
await self._generate_sync_entry_for_to_device(sync_result_builder)
1760-
1761-
logger.debug("Fetching OTK data")
1762-
device_id = sync_config.device_id
1763-
one_time_keys_count: JsonMapping = {}
1764-
unused_fallback_key_types: List[str] = []
1765-
if device_id:
1766-
# TODO: We should have a way to let clients differentiate between the states of:
1767-
# * no change in OTK count since the provided since token
1768-
# * the server has zero OTKs left for this device
1769-
# Spec issue: https://github.com/matrix-org/matrix-doc/issues/3298
1770-
one_time_keys_count = await self.store.count_e2e_one_time_keys(
1771-
user_id, device_id
1772-
)
1773-
unused_fallback_key_types = list(
1774-
await self.store.get_e2e_unused_fallback_key_types(user_id, device_id)
1775-
)
1776-
1777-
num_events = 0
1778-
1779-
# debug for https://github.com/matrix-org/synapse/issues/9424
1780-
for joined_room in sync_result_builder.joined:
1781-
num_events += len(joined_room.timeline.events)
1782-
1783-
log_kv(
1784-
{
1785-
"joined_rooms_in_result": len(sync_result_builder.joined),
1786-
"events_in_result": num_events,
1787-
}
1788-
)
1789-
1790-
logger.debug("Sync response calculation complete")
1791-
return SyncResult(
1792-
presence=sync_result_builder.presence,
1793-
account_data=sync_result_builder.account_data,
1794-
joined=sync_result_builder.joined,
1795-
invited=sync_result_builder.invited,
1796-
knocked=sync_result_builder.knocked,
1797-
archived=sync_result_builder.archived,
1798-
to_device=sync_result_builder.to_device,
1799-
device_lists=device_lists,
1800-
device_one_time_keys_count=one_time_keys_count,
1801-
device_unused_fallback_key_types=unused_fallback_key_types,
1802-
next_batch=sync_result_builder.now_token,
1803-
)
1835+
return sync_result_builder
18041836

18051837
@measure_func("_generate_sync_entry_for_device_list")
18061838
async def _generate_sync_entry_for_device_list(

0 commit comments

Comments
 (0)