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

Commit 40901af

Browse files
authored
Pass the device ID around in the presence handler (#16171)
Refactoring to pass the device ID (in addition to the user ID) through the presence handler (specifically the `user_syncing`, `set_state`, and `bump_presence_active_time` methods and their replication versions).
1 parent 1bf1436 commit 40901af

File tree

11 files changed

+91
-30
lines changed

11 files changed

+91
-30
lines changed

changelog.d/16171.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Track per-device information in the presence code.

synapse/handlers/events.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ async def get_stream(
6767

6868
context = await presence_handler.user_syncing(
6969
requester.user.to_string(),
70+
requester.device_id,
7071
affect_presence=affect_presence,
7172
presence_state=PresenceState.ONLINE,
7273
)

synapse/handlers/message.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,7 +1921,10 @@ async def persist_and_notify_client_events(
19211921
# We don't want to block sending messages on any presence code. This
19221922
# matters as sometimes presence code can take a while.
19231923
run_as_background_process(
1924-
"bump_presence_active_time", self._bump_active_time, requester.user
1924+
"bump_presence_active_time",
1925+
self._bump_active_time,
1926+
requester.user,
1927+
requester.device_id,
19251928
)
19261929

19271930
async def _notify() -> None:
@@ -1958,10 +1961,10 @@ async def _maybe_kick_guest_users(
19581961
logger.info("maybe_kick_guest_users %r", current_state)
19591962
await self.hs.get_room_member_handler().kick_guest_users(current_state)
19601963

1961-
async def _bump_active_time(self, user: UserID) -> None:
1964+
async def _bump_active_time(self, user: UserID, device_id: Optional[str]) -> None:
19621965
try:
19631966
presence = self.hs.get_presence_handler()
1964-
await presence.bump_presence_active_time(user)
1967+
await presence.bump_presence_active_time(user, device_id)
19651968
except Exception:
19661969
logger.exception("Error bumping presence active time")
19671970

synapse/handlers/presence.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,11 @@ def __init__(self, hs: "HomeServer"):
165165

166166
@abc.abstractmethod
167167
async def user_syncing(
168-
self, user_id: str, affect_presence: bool, presence_state: str
168+
self,
169+
user_id: str,
170+
device_id: Optional[str],
171+
affect_presence: bool,
172+
presence_state: str,
169173
) -> ContextManager[None]:
170174
"""Returns a context manager that should surround any stream requests
171175
from the user.
@@ -176,6 +180,7 @@ async def user_syncing(
176180
177181
Args:
178182
user_id: the user that is starting a sync
183+
device_id: the user's device that is starting a sync
179184
affect_presence: If false this function will be a no-op.
180185
Useful for streams that are not associated with an actual
181186
client that is being used by a user.
@@ -252,6 +257,7 @@ async def current_state_for_user(self, user_id: str) -> UserPresenceState:
252257
async def set_state(
253258
self,
254259
target_user: UserID,
260+
device_id: Optional[str],
255261
state: JsonDict,
256262
force_notify: bool = False,
257263
is_sync: bool = False,
@@ -260,6 +266,7 @@ async def set_state(
260266
261267
Args:
262268
target_user: The ID of the user to set the presence state of.
269+
device_id: the device that the user is setting the presence state of.
263270
state: The presence state as a JSON dictionary.
264271
force_notify: Whether to force notification of the update to clients.
265272
is_sync: True if this update was from a sync, which results in
@@ -269,7 +276,9 @@ async def set_state(
269276
"""
270277

271278
@abc.abstractmethod
272-
async def bump_presence_active_time(self, user: UserID) -> None:
279+
async def bump_presence_active_time(
280+
self, user: UserID, device_id: Optional[str]
281+
) -> None:
273282
"""We've seen the user do something that indicates they're interacting
274283
with the app.
275284
"""
@@ -381,7 +390,9 @@ async def send_full_presence_to_users(self, user_ids: StrCollection) -> None:
381390
# We set force_notify=True here so that this presence update is guaranteed to
382391
# increment the presence stream ID (which resending the current user's presence
383392
# otherwise would not do).
384-
await self.set_state(UserID.from_string(user_id), state, force_notify=True)
393+
await self.set_state(
394+
UserID.from_string(user_id), None, state, force_notify=True
395+
)
385396

386397
async def is_visible(self, observed_user: UserID, observer_user: UserID) -> bool:
387398
raise NotImplementedError(
@@ -481,7 +492,11 @@ def send_stop_syncing(self) -> None:
481492
self.send_user_sync(user_id, False, last_sync_ms)
482493

483494
async def user_syncing(
484-
self, user_id: str, affect_presence: bool, presence_state: str
495+
self,
496+
user_id: str,
497+
device_id: Optional[str],
498+
affect_presence: bool,
499+
presence_state: str,
485500
) -> ContextManager[None]:
486501
"""Record that a user is syncing.
487502
@@ -495,6 +510,7 @@ async def user_syncing(
495510
# what the spec wants.
496511
await self.set_state(
497512
UserID.from_string(user_id),
513+
device_id,
498514
state={"presence": presence_state},
499515
is_sync=True,
500516
)
@@ -592,6 +608,7 @@ def get_currently_syncing_users_for_replication(self) -> Iterable[str]:
592608
async def set_state(
593609
self,
594610
target_user: UserID,
611+
device_id: Optional[str],
595612
state: JsonDict,
596613
force_notify: bool = False,
597614
is_sync: bool = False,
@@ -600,6 +617,7 @@ async def set_state(
600617
601618
Args:
602619
target_user: The ID of the user to set the presence state of.
620+
device_id: the device that the user is setting the presence state of.
603621
state: The presence state as a JSON dictionary.
604622
force_notify: Whether to force notification of the update to clients.
605623
is_sync: True if this update was from a sync, which results in
@@ -622,12 +640,15 @@ async def set_state(
622640
await self._set_state_client(
623641
instance_name=self._presence_writer_instance,
624642
user_id=user_id,
643+
device_id=device_id,
625644
state=state,
626645
force_notify=force_notify,
627646
is_sync=is_sync,
628647
)
629648

630-
async def bump_presence_active_time(self, user: UserID) -> None:
649+
async def bump_presence_active_time(
650+
self, user: UserID, device_id: Optional[str]
651+
) -> None:
631652
"""We've seen the user do something that indicates they're interacting
632653
with the app.
633654
"""
@@ -638,7 +659,9 @@ async def bump_presence_active_time(self, user: UserID) -> None:
638659
# Proxy request to instance that writes presence
639660
user_id = user.to_string()
640661
await self._bump_active_client(
641-
instance_name=self._presence_writer_instance, user_id=user_id
662+
instance_name=self._presence_writer_instance,
663+
user_id=user_id,
664+
device_id=device_id,
642665
)
643666

644667

@@ -943,7 +966,9 @@ async def _handle_timeouts(self) -> None:
943966

944967
return await self._update_states(changes)
945968

946-
async def bump_presence_active_time(self, user: UserID) -> None:
969+
async def bump_presence_active_time(
970+
self, user: UserID, device_id: Optional[str]
971+
) -> None:
947972
"""We've seen the user do something that indicates they're interacting
948973
with the app.
949974
"""
@@ -966,6 +991,7 @@ async def bump_presence_active_time(self, user: UserID) -> None:
966991
async def user_syncing(
967992
self,
968993
user_id: str,
994+
device_id: Optional[str],
969995
affect_presence: bool = True,
970996
presence_state: str = PresenceState.ONLINE,
971997
) -> ContextManager[None]:
@@ -977,7 +1003,8 @@ async def user_syncing(
9771003
when users disconnect/reconnect.
9781004
9791005
Args:
980-
user_id
1006+
user_id: the user that is starting a sync
1007+
device_id: the user's device that is starting a sync
9811008
affect_presence: If false this function will be a no-op.
9821009
Useful for streams that are not associated with an actual
9831010
client that is being used by a user.
@@ -993,6 +1020,7 @@ async def user_syncing(
9931020
# what the spec wants.
9941021
await self.set_state(
9951022
UserID.from_string(user_id),
1023+
device_id,
9961024
state={"presence": presence_state},
9971025
is_sync=True,
9981026
)
@@ -1163,6 +1191,7 @@ async def incoming_presence(self, origin: str, content: JsonDict) -> None:
11631191
async def set_state(
11641192
self,
11651193
target_user: UserID,
1194+
device_id: Optional[str],
11661195
state: JsonDict,
11671196
force_notify: bool = False,
11681197
is_sync: bool = False,
@@ -1171,6 +1200,7 @@ async def set_state(
11711200
11721201
Args:
11731202
target_user: The ID of the user to set the presence state of.
1203+
device_id: the device that the user is setting the presence state of.
11741204
state: The presence state as a JSON dictionary.
11751205
force_notify: Whether to force notification of the update to clients.
11761206
is_sync: True if this update was from a sync, which results in

synapse/replication/http/presence.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
import logging
16-
from typing import TYPE_CHECKING, Tuple
16+
from typing import TYPE_CHECKING, Optional, Tuple
1717

1818
from twisted.web.server import Request
1919

@@ -51,14 +51,14 @@ def __init__(self, hs: "HomeServer"):
5151
self._presence_handler = hs.get_presence_handler()
5252

5353
@staticmethod
54-
async def _serialize_payload(user_id: str) -> JsonDict: # type: ignore[override]
55-
return {}
54+
async def _serialize_payload(user_id: str, device_id: Optional[str]) -> JsonDict: # type: ignore[override]
55+
return {"device_id": device_id}
5656

5757
async def _handle_request( # type: ignore[override]
5858
self, request: Request, content: JsonDict, user_id: str
5959
) -> Tuple[int, JsonDict]:
6060
await self._presence_handler.bump_presence_active_time(
61-
UserID.from_string(user_id)
61+
UserID.from_string(user_id), content.get("device_id")
6262
)
6363

6464
return (200, {})
@@ -95,11 +95,13 @@ def __init__(self, hs: "HomeServer"):
9595
@staticmethod
9696
async def _serialize_payload( # type: ignore[override]
9797
user_id: str,
98+
device_id: Optional[str],
9899
state: JsonDict,
99100
force_notify: bool = False,
100101
is_sync: bool = False,
101102
) -> JsonDict:
102103
return {
104+
"device_id": device_id,
103105
"state": state,
104106
"force_notify": force_notify,
105107
"is_sync": is_sync,
@@ -110,6 +112,7 @@ async def _handle_request( # type: ignore[override]
110112
) -> Tuple[int, JsonDict]:
111113
await self._presence_handler.set_state(
112114
UserID.from_string(user_id),
115+
content.get("device_id"),
113116
content["state"],
114117
content["force_notify"],
115118
content.get("is_sync", False),

synapse/rest/client/presence.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ async def on_PUT(
9797
raise SynapseError(400, "Unable to parse state")
9898

9999
if self._use_presence:
100-
await self.presence_handler.set_state(user, state)
100+
await self.presence_handler.set_state(user, requester.device_id, state)
101101

102102
return 200, {}
103103

synapse/rest/client/read_marker.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ async def on_POST(
5252
) -> Tuple[int, JsonDict]:
5353
requester = await self.auth.get_user_by_req(request)
5454

55-
await self.presence_handler.bump_presence_active_time(requester.user)
55+
await self.presence_handler.bump_presence_active_time(
56+
requester.user, requester.device_id
57+
)
5658

5759
body = parse_json_object_from_request(request)
5860

synapse/rest/client/receipts.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ async def on_POST(
9494
Codes.INVALID_PARAM,
9595
)
9696

97-
await self.presence_handler.bump_presence_active_time(requester.user)
97+
await self.presence_handler.bump_presence_active_time(
98+
requester.user, requester.device_id
99+
)
98100

99101
if receipt_type == ReceiptTypes.FULLY_READ:
100102
await self.read_marker_handler.received_client_read_marker(

synapse/rest/client/room.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,9 @@ async def on_PUT(
12291229

12301230
content = parse_json_object_from_request(request)
12311231

1232-
await self.presence_handler.bump_presence_active_time(requester.user)
1232+
await self.presence_handler.bump_presence_active_time(
1233+
requester.user, requester.device_id
1234+
)
12331235

12341236
# Limit timeout to stop people from setting silly typing timeouts.
12351237
timeout = min(content.get("timeout", 30000), 120000)

synapse/rest/client/sync.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
205205

206206
context = await self.presence_handler.user_syncing(
207207
user.to_string(),
208+
requester.device_id,
208209
affect_presence=affect_presence,
209210
presence_state=set_presence,
210211
)

0 commit comments

Comments
 (0)