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

Commit cdd985c

Browse files
committed
Only send a presence state to a destination once (#10165)
It turns out that we were sending the same presence state to a remote potentially multiple times.
1 parent 5e0b471 commit cdd985c

File tree

2 files changed

+13
-13
lines changed

2 files changed

+13
-13
lines changed

changelog.d/10165.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug where Synapse could send the same presence update to a remote twice.

synapse/handlers/presence.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -299,14 +299,14 @@ async def maybe_send_presence_to_interested_destinations(
299299
if not states:
300300
return
301301

302-
hosts_and_states = await get_interested_remotes(
302+
hosts_to_states = await get_interested_remotes(
303303
self.store,
304304
self.presence_router,
305305
states,
306306
)
307307

308-
for destinations, states in hosts_and_states:
309-
self._federation.send_presence_to_destinations(states, destinations)
308+
for destination, host_states in hosts_to_states.items():
309+
self._federation.send_presence_to_destinations(host_states, [destination])
310310

311311
async def send_full_presence_to_users(self, user_ids: Collection[str]):
312312
"""
@@ -842,15 +842,15 @@ async def _update_states(
842842
if to_federation_ping:
843843
federation_presence_out_counter.inc(len(to_federation_ping))
844844

845-
hosts_and_states = await get_interested_remotes(
845+
hosts_to_states = await get_interested_remotes(
846846
self.store,
847847
self.presence_router,
848848
list(to_federation_ping.values()),
849849
)
850850

851-
for destinations, states in hosts_and_states:
851+
for destination, states in hosts_to_states.items():
852852
self._federation_queue.send_presence_to_destinations(
853-
states, destinations
853+
states, [destination]
854854
)
855855

856856
async def _handle_timeouts(self) -> None:
@@ -1975,7 +1975,7 @@ async def get_interested_remotes(
19751975
store: DataStore,
19761976
presence_router: PresenceRouter,
19771977
states: List[UserPresenceState],
1978-
) -> List[Tuple[Collection[str], List[UserPresenceState]]]:
1978+
) -> Dict[str, Set[UserPresenceState]]:
19791979
"""Given a list of presence states figure out which remote servers
19801980
should be sent which.
19811981
@@ -1987,11 +1987,9 @@ async def get_interested_remotes(
19871987
states: A list of incoming user presence updates.
19881988
19891989
Returns:
1990-
A list of 2-tuples of destinations and states, where for
1991-
each tuple the list of UserPresenceState should be sent to each
1992-
destination
1990+
A map from destinations to presence states to send to that destination.
19931991
"""
1994-
hosts_and_states = [] # type: List[Tuple[Collection[str], List[UserPresenceState]]]
1992+
hosts_and_states: Dict[str, Set[UserPresenceState]] = {}
19951993

19961994
# First we look up the rooms each user is in (as well as any explicit
19971995
# subscriptions), then for each distinct room we look up the remote
@@ -2003,11 +2001,12 @@ async def get_interested_remotes(
20032001
for room_id, states in room_ids_to_states.items():
20042002
user_ids = await store.get_users_in_room(room_id)
20052003
hosts = {get_domain_from_id(user_id) for user_id in user_ids}
2006-
hosts_and_states.append((hosts, states))
2004+
for host in hosts:
2005+
hosts_and_states.setdefault(host, set()).update(states)
20072006

20082007
for user_id, states in users_to_states.items():
20092008
host = get_domain_from_id(user_id)
2010-
hosts_and_states.append(([host], states))
2009+
hosts_and_states.setdefault(host, set()).update(states)
20112010

20122011
return hosts_and_states
20132012

0 commit comments

Comments
 (0)