1717from itertools import chain
1818from typing import TYPE_CHECKING , AbstractSet , Mapping
1919
20+ import attr
2021from prometheus_client import Histogram
2122from typing_extensions import assert_never
2223
@@ -1190,22 +1191,21 @@ async def get_room_sync_data(
11901191 if prev_room_sync_config is not None :
11911192 # Check if there are any changes to the required state config
11921193 # that we need to handle.
1193- changed_required_state_map , added_state_filter = (
1194- _required_state_changes (
1195- user .to_string (),
1196- prev_required_state_map = prev_room_sync_config .required_state_map ,
1197- request_required_state_map = expanded_required_state_map ,
1198- state_deltas = room_state_delta_id_map ,
1199- )
1194+ changes_return = _required_state_changes (
1195+ user .to_string (),
1196+ prev_required_state_map = prev_room_sync_config .required_state_map ,
1197+ request_required_state_map = expanded_required_state_map ,
1198+ state_deltas = room_state_delta_id_map ,
12001199 )
1200+ changed_required_state_map = changes_return .required_state_map_change
12011201
1202- if added_state_filter :
1202+ if changes_return . added_state_filter :
12031203 # Some state entries got added, so we pull out the current
12041204 # state for them. If we don't do this we'd only send down new deltas.
12051205 state_ids = await self .get_current_state_ids_at (
12061206 room_id = room_id ,
12071207 room_membership_for_user_at_to_token = room_membership_for_user_at_to_token ,
1208- state_filter = added_state_filter ,
1208+ state_filter = changes_return . added_state_filter ,
12091209 to_token = to_token ,
12101210 )
12111211 room_state_delta_id_map .update (state_ids )
@@ -1499,13 +1499,28 @@ async def _get_bump_stamp(
14991499 return None
15001500
15011501
1502+ @attr .s (auto_attribs = True )
1503+ class _RequiredStateChangesReturn :
1504+ """Return type for _required_state_changes.
1505+
1506+ Attributes:
1507+ required_state_map_change: The updated required state map to store in
1508+ the room config, or None if there is no change.
1509+ added_state_filter: The state filter to use to fetch any additional
1510+ current state that needs to be returned to the client.
1511+ """
1512+
1513+ required_state_map_change : Mapping [str , AbstractSet [str ]] | None
1514+ added_state_filter : StateFilter
1515+
1516+
15021517def _required_state_changes (
15031518 user_id : str ,
15041519 * ,
15051520 prev_required_state_map : Mapping [str , AbstractSet [str ]],
15061521 request_required_state_map : Mapping [str , AbstractSet [str ]],
15071522 state_deltas : StateMap [str ],
1508- ) -> tuple [ Mapping [ str , AbstractSet [ str ]] | None , StateFilter ] :
1523+ ) -> _RequiredStateChangesReturn :
15091524 """Calculates the changes between the required state room config from the
15101525 previous requests compared with the current request.
15111526
@@ -1518,16 +1533,13 @@ def _required_state_changes(
15181533 This function tries to ensure to handle the case where a state entry is
15191534 added, removed and then added again to the required state. In that case we
15201535 only want to re-send that entry down sync if it has changed.
1521-
1522- Returns:
1523- A 2-tuple of updated required state config (or None if there is no update)
1524- and the state filter to use to fetch extra current state that we need to
1525- return.
15261536 """
15271537 if prev_required_state_map == request_required_state_map :
15281538 # There has been no change. Return immediately.
1529- return None , StateFilter .none ()
1530-
1539+ return _RequiredStateChangesReturn (
1540+ required_state_map_change = None ,
1541+ added_state_filter = StateFilter .none (),
1542+ )
15311543 prev_wildcard = prev_required_state_map .get (StateValues .WILDCARD , set ())
15321544 request_wildcard = request_required_state_map .get (StateValues .WILDCARD , set ())
15331545
@@ -1536,17 +1548,26 @@ def _required_state_changes(
15361548 # already fetching everything, we don't have to fetch anything now that they've
15371549 # narrowed.
15381550 if StateValues .WILDCARD in prev_wildcard :
1539- return request_required_state_map , StateFilter .none ()
1551+ return _RequiredStateChangesReturn (
1552+ required_state_map_change = request_required_state_map ,
1553+ added_state_filter = StateFilter .none (),
1554+ )
15401555
15411556 # If a event type wildcard has been added or removed we don't try and do
15421557 # anything fancy, and instead always update the effective room required
15431558 # state config to match the request.
15441559 if request_wildcard - prev_wildcard :
15451560 # Some keys were added, so we need to fetch everything
1546- return request_required_state_map , StateFilter .all ()
1561+ return _RequiredStateChangesReturn (
1562+ required_state_map_change = request_required_state_map ,
1563+ added_state_filter = StateFilter .all (),
1564+ )
15471565 if prev_wildcard - request_wildcard :
15481566 # Keys were only removed, so we don't have to fetch everything.
1549- return request_required_state_map , StateFilter .none ()
1567+ return _RequiredStateChangesReturn (
1568+ required_state_map_change = request_required_state_map ,
1569+ added_state_filter = StateFilter .none (),
1570+ )
15501571
15511572 # Contains updates to the required state map compared with the previous room
15521573 # config. This has the same format as `RoomSyncConfig.required_state`
@@ -1722,6 +1743,12 @@ def _required_state_changes(
17221743 # Remove entries with empty state keys.
17231744 new_required_state_map .pop (event_type , None )
17241745
1725- return new_required_state_map , added_state_filter
1746+ return _RequiredStateChangesReturn (
1747+ required_state_map_change = new_required_state_map ,
1748+ added_state_filter = added_state_filter ,
1749+ )
17261750 else :
1727- return None , added_state_filter
1751+ return _RequiredStateChangesReturn (
1752+ required_state_map_change = None ,
1753+ added_state_filter = added_state_filter ,
1754+ )
0 commit comments