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

Register the /devices endpoint on workers. #9092

Merged
merged 2 commits into from Jan 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/9092.feature
@@ -0,0 +1 @@
Add experimental support for handling `/devices` API on worker processes.
1 change: 1 addition & 0 deletions docs/workers.md
Expand Up @@ -214,6 +214,7 @@ expressions:
^/_matrix/client/(api/v1|r0|unstable)/rooms/.*/members$
^/_matrix/client/(api/v1|r0|unstable)/rooms/.*/state$
^/_matrix/client/(api/v1|r0|unstable)/account/3pid$
^/_matrix/client/(api/v1|r0|unstable)/devices$
^/_matrix/client/(api/v1|r0|unstable)/keys/query$
^/_matrix/client/(api/v1|r0|unstable)/keys/changes$
^/_matrix/client/versions$
Expand Down
2 changes: 2 additions & 0 deletions synapse/app/generic_worker.py
Expand Up @@ -107,6 +107,7 @@
AccountDataServlet,
RoomAccountDataServlet,
)
from synapse.rest.client.v2_alpha.devices import DevicesRestServlet
from synapse.rest.client.v2_alpha.keys import (
KeyChangesServlet,
KeyQueryServlet,
Expand Down Expand Up @@ -509,6 +510,7 @@ def _listen_http(self, listener_config: ListenerConfig):
RegisterRestServlet(self).register(resource)
LoginRestServlet(self).register(resource)
ThreepidRestServlet(self).register(resource)
DevicesRestServlet(self).register(resource)
KeyQueryServlet(self).register(resource)
OneTimeKeyServlet(self).register(resource)
KeyChangesServlet(self).register(resource)
Expand Down
41 changes: 30 additions & 11 deletions synapse/storage/databases/main/client_ips.py
Expand Up @@ -407,6 +407,34 @@ def _prune_old_user_ips_txn(txn):
"_prune_old_user_ips", _prune_old_user_ips_txn
)

async def get_last_client_ip_by_device(
self, user_id: str, device_id: Optional[str]
) -> Dict[Tuple[str, str], dict]:
"""For each device_id listed, give the user_ip it was last seen on.

The result might be slightly out of date as client IPs are inserted in batches.

Args:
user_id: The user to fetch devices for.
device_id: If None fetches all devices for the user

Returns:
A dictionary mapping a tuple of (user_id, device_id) to dicts, with
keys giving the column names from the devices table.
"""

keyvalues = {"user_id": user_id}
if device_id is not None:
keyvalues["device_id"] = device_id

res = await self.db_pool.simple_select_list(
table="devices",
keyvalues=keyvalues,
retcols=("user_id", "ip", "user_agent", "device_id", "last_seen"),
)

return {(d["user_id"], d["device_id"]): d for d in res}


class ClientIpStore(ClientIpWorkerStore):
def __init__(self, database: DatabasePool, db_conn, hs):
Expand Down Expand Up @@ -512,18 +540,9 @@ async def get_last_client_ip_by_device(
A dictionary mapping a tuple of (user_id, device_id) to dicts, with
keys giving the column names from the devices table.
"""
ret = await super().get_last_client_ip_by_device(user_id, device_id)

keyvalues = {"user_id": user_id}
if device_id is not None:
keyvalues["device_id"] = device_id

res = await self.db_pool.simple_select_list(
table="devices",
keyvalues=keyvalues,
retcols=("user_id", "ip", "user_agent", "device_id", "last_seen"),
)

ret = {(d["user_id"], d["device_id"]): d for d in res}
# Update what is retrieved from the database with data which is pending insertion.
for key in self._batch_row_update:
uid, access_token, ip = key
if uid == user_id:
Expand Down